Поиск

Известные ошибки и недостатки дизайна MySQL

Ошибки в версии 3.23, исправленные в более поздних версиях MySQL
Перечисленные ниже известные ошибки не были исправлены в версии 3.23, посколь­ку их исправление привело бы к изменению большой части кода, что могло, в свою оче­редь, вызвать появление других, даже намного худших ошибок. Эти ошибки классифи­цируются как ;не критические; или ;терпимые;.

  1. Можно возникнуть взаимная блокировка, если использовать LOCK TABLE для бло кировки нескольких таблиц и затем в том же соединении удалить одну из них оператором DROP TABLE в то время, когда другой поток пытается ее заблокиро вать. (Для устранения взаимной блокировки можно с помощью команды KILL за вершить любой из участвующих в ней потоков.) Эта проблема была решена в MySQL 4.0.12.
  2. SELECT МАХ{ключевой_столбец) FROM tl, t2,t3. .., где одна из таблиц пуста, не возвращает NULL, а возвращает максимальное значение столбца. Это исправлено в MySQL 4.0.11.
  3. DELETE FROM таблица_Ьеар без конструкции WHERE не работает на блокированной НЕАР-таблице.
Ошибки в версии 4.0, исправленные в более поздних версиях
Перечисленные ниже известные ошибки не были исправлены в версии 4.0, поскольку их исправление привело бы к изменению большой части кода, что могло, в свою оче­редь, вызвать появление других, даже намного худших ошибок. Эти ошибки также клас­сифицируются, как ;не критические; или ;терпимые;.

  1. В UNION первый же оператор SELECT определяет свойства результирующих столб­ цов - тип, максимальную длину (max_length), возможность записи значений NULL. Это было исправлено в MySQL 4.1.1 - значения свойств столбцов определяются на основании строк из всех частей UNION.
  2. В операторе DELETE по нескольким таблицам невозможно обращаться к таблицам по псевдонимам. Исправлено в MySQL 4.1.
Открытые ошибки и недостатки дизайна MySQL
Следующие проблемы уже известны и решение их имеет наивысший приоритет:

  1. Удаление ограничений FOREIGN KEY не работает на реплицированной копии, по­ скольку ограничение может иметь другое имя, чем в исходной базе.
  2. REPLACE (и LOAD DATA С опцией REPLACE) не вызывает ON DELETE CASCADE (каскад­ ного удаления).
  3. Невозможно смешивать UNION ALL и UNION DISTINCT в одном и том же запросе. Если используется ALL для одного из UNION, это касается их всех.

а Если один пользователь запустил долго выполняемую транзакцию, а другой уда­лил таблицу, которая обновлялась в этой транзакции, то существует небольшая вероятность того, что в бинарный протокол попадет команда DROP TABLE, прежде чем таблица будет задействована в транзакции. Мы планируем исправить это в версии 5.0, заставив оператор DROP TABLE ожидать до тех пор, пока таблица ис­пользуется хотя бы в одной транзакции.

  1. При вставке больших целочисленных значений (между 263 и 264 - 1) в десятичный или строковый столбец, оно вставляется как отрицательное значение, поскольку число оценивается в контексте целого со знаком. Мы планируем исправить это в MySQL 4.1.
  2. FLUSH TABLES WITH READ LOCK не блокирует CREATE TABLE ИЛИ COMMIT, ЧТО может привести к проблемам с позицией в бинарном протоколе при выполнении полного резервного копирования таблиц и бинарного протокола.
  3. ANALYZE TABLE для таблиц BDB в некоторых случаях может приводить к тому, что таблицы становятся недоступными до тех пор, пока не будет перезапущен mysqld. Если это случается, в файл ошибок MySQL добавляется такая строка:

001207 22:07:56 bdb: log_flush: LSN past current end-of-log

  1. MySQL принимает скобки в конструкции FROM оператора SELECT, но молча игно­ рирует их. Причина того, что сообщения об ошибках не выдаются, состоит в том, что очень многие клиенты при автоматической генерации запросов добавляют скобки в конструкцию FROM, даже если в этом нет необходимости.
  2. Объединение многих RIGHT JOIN или комбинаций LEFT JOIN и RIGHT JOIN в од- ном запросе могут не приводить к корректному результату, потому что MySQL генерирует строки NULL для таблицы, следующей за LEFT JOIN или перед RIGHT JOIN. Это будет исправлено в 5.0, одновременно мы добавим поддержку скобок в предложение FROM.
  3. Не выполняйте ALTER TABLE для таблицы BDB, участвующей в многотабличных транзакциях, до тех пор, пока все они не завершатся. (Транзакции могут быть проигнорированы.)

Я Команды ANALYZE TABLE, OPTIMIZE TABLE И REPAIR TABLE могут вызывать про­блемы в таблицах, в которых используется INSERT DELAYED.

  1. Выполнение LOCK TABLE... и FLUSH TABLES... не гарантирует, что в таблице не окажется наполовину завершенных транзакций.
  2. Таблицы BDB открываются несколько медленно. Если в базе данных есть много таблиц BDB, потребуется немало времени, чтобы запустить клиент mysql с опцией -А или выполнить rehash. В особенности это касается тех случаев, когда имеется большой табличный кэш.
  3. Репликация использует протоколирование уровня запросов. Реплицируемая база фиксирует выполняемые запросы в бинарном протоколе. Это очень быстрый, компактный и эффективный метод протоколирования, который в большинстве случаев работает превосходно. Однако, хотя нам и не известны такие случаи, су­ ществует теоретическая возможность того, что данные в исходной и целевой базе окажутся разными, если запрос составлен таким образом, что модификация дан­ ных будет недетерминированной. Это остается на совести оптимизатора запросов. (Вообще говоря, это очень плохая практика, даже за рамками темы репликации!). Например:

• Операторы CREATE.. .SELECT или INSERT.. .SELECT, которые вставляют нуле­вые или NULL-значения в столбцы AUTO INCREMENT. DELETE, если выполняется для таблицы, имеющей внешние ключи со свойством ON DELETE CASCADE.

  • REPLACE.. .SELECT, INSERT IGNORE.. .SELECT, если во вставляемых данных присутствуют дублированные ключи.

Если и только если все эти запросы не содержат конструкцию ORDER BY, гаранти­руется детерминированный порядок. Например, для INSERT.. .SELECT без ORDER BY, оператор SELECT может вернуть за­писи в другом порядке (что может оказаться результатом того, что записи имеют разный ранг и, следовательно, разные номера в столбцах AUTO_INCREMENT), в зави­симости от того, как сработают оптимизаторы в исходной и целевой базах при ре­пликации. Запросы могут быть оптимизированы различным образом в двух базах, если:

  1. Файлы, используемые в запросах, не одинаковы. Например, OPTIMIZE TABLE был запущен для исходных таблиц и не запускался для целевых (для исправ­ ления ЭТОГО, начиная С MySQL 4.1.1, OPTIMIZE TABLE, ANALYZE TABLE И REPAIR TABLE записываются в бинарный протокол).
  2. Исходная и целевая таблицы обрабатываются разными механизмами хранения (это возможно; например, вы можете использовать InnoDB в исходной репли- цируемой базе и MyISAM - в целевой базе, если в ней нет дискового простран­ ства достаточного объема).
  3. Размер буферов разный (key_buf fer_size и так далее).
  4. Исходная и целевая базы работают под управлением разных версий MySQL, и коды оптимизаторов у них отличаются.

Эта проблема может также затронуть восстановление базы с использованием mysqlbinlogImysql. Наилучший способ избежать этих проблем во всех случаях - добавлять конструк­цию ORDER BY к подобным недетерминированным запросам, дабы гарантировать, что строки сохраняются и модифицируются в одном и том же порядке. В будущих версиях MySQL мы будем автоматически добавлять ORDER BY туда, где это необ­ходимо. Следующие проблемы известны и будут решены в надлежащее время:

  1. Имена файлов протоколов основаны на имени хоста (если только явно не указаны при запуске). На сегодняшний день, если изменяется имя хоста, нужно использо­ вать опции наподобие -1од-Ып=старое_имя_хоста-Ып. Другой способ состоит в том, чтобы просто переименовать старые файлы в соответствии с изменением имени хоста.
  2. mysqlbinlog не удаляет временные файлы, которые остаются после выполнения команды LOAD DATA INFILE.
  3. RENAME не работает на временных таблицах и таблицах, используемых в таблицах

MERGE.

  • При использовании функции RPAD() в запросах, выполнение которых потребует создания временных таблиц, во всех результирующих строках заключительные пробелы будут удалены. Ниже показан пример такого запроса.

    SELECT RPAD(tl.columnl, 50, ' ') AS f2, RPAD(t2.column2, 50, ' ') AS fl FROM tablel as tl LEFT JOIN table2 AS t2 ON tl.record=t2.joinID ORDER BY t2.record; Вследствие этой ошибки вы не получите завершающих пробелов в результирую­щих значениях. Эта проблема также относится ко всем остальным строковым функциям, добавляющим пробелы справа. Причиной является то, что НЕАР-таблицы, которые используются вначале для вре­менных таблиц, не могут работать со столбцами типа VARCHAR. Подобное поведение присуще всем версиям MySQL и будет исправлено в одном из выпусков в рамках серии 4.1.
  • Из-за способа хранения файла определений таблиц невозможно использовать символ 255 (CHAR(255)) в именах таблиц, столбцов или перечислений. Исправле­ ние запланировано в версии 5.1, когда мы будем иметь новый формат файлов оп­ ределения таблиц.

При использовании SET CHARACTER SET невозможно использовать переведенные символы в именах баз данных, таблиц и столбцов.

  1. Невозможно использовать шаблонные символы '_', '%' вместе с ESCAPE в like. .. ESCAPE.
  2. Если есть столбец типа DECIMAL, в котором одно и то же число сохраняется в раз­ ных форматах (например, +01.00, 1.00, 01.00), то GROUP BY может рассматривать такие значения как различные.
  3. Невозможно собрать сервер в другом каталоге при использовании потоков MIT- pthreads. Поскольку для этого нужно изменять потоки MIT-pthreads, по всей ви­ димости, исправлять мы это не будем.
  4. Значения типа BLOB не могут ;надежно; применяться в GROUP BY, ORDER BY или DISTINCT. В этих случаях для сравнения значений BLOB используются только пер­ вые max_sort_length байт. Значение по умолчанию max_sort_length равно 1024 байта. Это может быть изменено во время запуска сервера. Чтобы обойти это ог­ раничение, в большинстве случаев можно применить подстроки, например: SELECT DISTINCT LEFT(столбец_Ьlob, 2048) FROM имя_таблицы
  5. Вычислительные операции выполняются над типами BIGINT и DOUBLE (оба они обычно имеют длину 64 байта). Какую точность вы получите, зависит от функ­ ции. Общее правило звучит так: поразрядные функции выполняются с точностью BIGINT, IF и ELT () - с точностью BIGINT или DOUBLE, все остальные - с точностью DOUBLE. Старайтесь избегать применения беззнаковых длинных значений, если они могут оказаться длиной более 63 бит (9223372036854775807) во всех случаях, кроме битовых полей. Версия MySQL 4.0 лучше справляется с BIGINT, чем версия MySQL 3.23.
  6. У всех строковых столбцов, кроме BLOB и TEXT, при извлечении из базы автомати­ чески удаляются завершающие пробелы. Для типа CHAR это нормально. Ошибка состоит в том, что столбцы VARCHAR обрабатываются точно так же.
  7. В одной таблице можно иметь не более 255 столбцов типа ENUM и SET.
  • В MIN (), МАХ () и других агрегатных функциях в настоящее время столбцы типов ENUM и SET сравниваются по их строковым значениям вместо того, чтобы делать это по относительному положению строки в наборе.
  • mysqld_safe перенаправляет все сообщения от mysqld в журнал mysqld. Одна свя­ занная с этим проблема состоит в том, что если запустить mysqladmin refresh для закрытия и повторного открытия журнала, стандартный поток вывода stdout и стандартный поток ошибок stderr остаются перенаправленными в старый жур­ нал. Если —log применяется интенсивно, нужно отредактировать mysqld_safe, чтобы он выводил протокол в имя_хоста.еп вместо имя_хоста.log. В этом слу­ чае можно легко использовать дисковое пространство, занятое старым журналом, удалив его и запустив mysqladmin refresh.
  • Оператор UPDATE обновляет столбцы слева направо. Если вы ссылаетесь на обнов­ ляемые столбцы, то получаете их новые значения вместо старых. Например, сле­ дующий оператор увеличит значение KEY на 2, а не на 1:

    mysql UPDATE имя_таблицыSET KEY=KEY+1,KEY=KEY+1;

  • Можно обращаться к множеству временных таблиц в одном запросе, но нельзя обращаться к одной и той же временной таблице более одного раза. Например, приведенный ниже оператор не работает: mysql SELECT * FROM temp_table, temp_table AS t2; ERROR 1137: Can't reopen table: 'temp_table' (ERROR 1137: Невозможноповторнооткрытьтаблицу: 'temp_table')
  • Оптимизатор может обрабатывать DISTINCT по-разному, когда используются ;скрытые; столбцы в объединении и когда они не используются. Скрытые столб­цы в объединении считаются частью результата (даже если они не показываются), тогда как в нормальных запросах скрытые столбцы не участвуют в сравнениях для DISTINCT. Возможно, мы исправим это в будущем, чтобы скрытые столбцы никогда не участвовали в вычислении DISTINCT. Ниже представлены соответствующие примеры: SELECT DISTINCT mp3id FROM band_downloads WHERE userid = 9 ORDER BY id DESC; и SELECT DISTINCT band_downloads.mp3id FROM band_downloads,band_mp3 WHERE band_downloads.userid = 9 AND band_mp3.id = band_downloads.mp3id ORDER BY band_downloads.id DESC; Во втором случае сервер MySQL 3.23.x может выдать две идентичные строки в результирующем наборе (поскольку значения скрытого столбца id у них различ­ны). Отметим, что это случается с запросами, где в результате не выводятся столбцы, участвующие в конструкции order by.
  • Поскольку MySQL позволяет работать с типами таблиц, для которых не поддер живаются транзакции, и поэтому невозможен откат, некоторые вещи работают здесь несколько иначе, чем в других серверах SQL. Это связано только с тем, что бы гарантировать, что откат никогда не понадобится MySQL для выполнения

SQL-операторов. Иногда это может оказаться неудобным, потому что значения столбцов должны проверяться самим приложением, но это дает существенный выигрыш в скорости, так как позволяет MySQL выполнить оптимизацию, кото­рую в противном случае было бы очень трудно реализовать. Если вы устанавливаете некорректное значение столбца, MySQL вместо отката пытается сохранить вместо него ;наилучшее возможное; значение. Информацию о том, как это происходит, можно найти в разделе Как MySQL работает с ограничениями.
• Если запускается PROCEDURE на запросе, возвратившем пустой результирующий набор, в некоторых случаях PROCEDURE не трансформирует столбцы.

  1. При создании таблиц типа MERGE не выполняется проверка входящих в них таблиц на предмет соответствия типов.
  2. Если вы используете ALTER TABLE вначале для добавления уникального индекса к таблице, включенной в MERGE, а затем пытаетесь добавить нормальный индекс к MERGE-таблице, порядок ключей будет разным, если существовал старый ключ, который был не уникальным для таблицы. Это происходит ввиду того, что alter TABLE помещает уникальные индексы перед нормальными индексами, чтобы как можно раньше обнаружить дублированные ключи.

Далее перечислены известные ошибки в ранних версиях MySQL.

  • В описанных ниже случаях может случиться аварийный отказ ядра.

  1. Обработчик отложенных вставок задерживает вставки в таблицу.
  2. LOCK TABLE С WRITE.
  3. FLUSH TABLE.

  • До версии сервера MySQL 3.23.2 оператор UPDATE, обновляющий значения клю­ чей, упомянутых в конструкции WHERE, мог аварийно завершиться, поскольку ключи используются для поиска записей, и одни и те же строки могли быть най­ дены по нескольку раз: UPDATE имя_таблицы SET KEY=KEY+1 WHERE KEY 100; Обходной путь выглядит следующим образом: UPDATE имя_таблицы SET KEY=KEY+1 WHERE KEY+0 100; Это работает потому, что сервер MySQL не использует индексы для выражений в конструкции WHERE.
  • До версии сервера MySQL 3.23 значения всех числовых типов трактовались как числа с фиксированной запятой. Это означало, что нужно было явно указывать, сколько десятичных знаков должно иметь поле с плавающей запятой. Все резуль­ таты возвращались с корректным количеством знаков.