Известные ошибки и недостатки проектирования в MySQL
Устранение следующих из выявленных проблем относится к числу первоочередных задач:
ANALYZE TABLE на таблицах BDB в некоторых случаях может сделать таблицу недоступной для использования, пока не произойдет перезапуск mysqld . При этом в файле ошибок MySQL можно будет увидеть ошибки, подобные следующим:
001207 22:07:56 bdb: log_flush: LSN past current end-of-log
Не следует выполнять ALTER TABLE на таблицах BDB , на которых осуществляются многокомандные транзакции, пока все эти транзакции не завершатся (возможно, данные транзакции будут проигнорированы).
ANALYZE TABLE , OPTIMIZE TABLE и REPAIR TABLE могут вызвать проблемы на таблицах, для которых используется INSERT DELAYED .
Выполнение LOCK TABLE ... и FLUSH TABLES ... не гарантирует, что на данной таблице нет исполняемых в текущий момент незаконченных транзакций.
Открытие таблиц BDB происходит несколько медленно. Если база данных содержит много таблиц BDB , то потребуется значительное время для использования клиента mysql на этой базе данных, если не применять опцию -A или если использовать rehash . Это особенно заметно при наличии большого табличного кэша.
Следующие проблемы также известны и будут устранены в свое время:
При использовании функции RPAD , или любой другой строковой функции, добавляющией пробелы в правую часть строки, в запросе, для которого MySQL будет создавать временные таблицы для его выполнения, все результирующие строки будут в результате обработаны RTRIM"ом (RTRIM"ed). Вот пример запроса:
SELECT RPAD(t1.field1, 50, " ") AS f2, RPAD(t2.field2, 50, " ") AS f1 FROM table1 as t1 LEFT JOIN table2 AS t2 ON t1.record=t2.joinID ORDER BY t2.record; В результате невозможно получить пробелы в правой части результирующего столбца. Такое поведение присутствует во всех версиях MySQL. Причина заключается в том, что HEAP-таблицы, которые в первую очередь используются для временных таблиц, неспособны работать с VARCHAR-столбцами. Такое поведение будет исправлено в одной из версий 4.1.
При использовании SET CHARACTER SET нельзя использовать преобразованные символы в именах базы данных, таблицы и столбца.
Нельзя использовать _ или % с ESCAPE в LIKE... ESCAPE .
Если в столбце DECIMAL число хранится в различных форматах (+01.00, 1.00, 01.00), то GROUP BY может рассматривать каждую величину как самостоятельную.
DELETE FROM merge_table при использовании без WHERE будет очищать только отображение для этой таблицы, а не удалять все данные в отображенных таблицах.
При использовании потоков MIT-pthreads нельзя расположить сервер вином каталоге. Поскольку для решения данной проблемы требуютсяизменения для потоков MIT-pthreads, маловероятно, что мы ее устраним(см. раздел Замечания по потокам MIT-pthreads).
Не обеспечивается "надежное" применение величин BLOB в GROUP BY или ORDER BY или DISTINCT . В этих случаях при сравнении величин BLOB используются только первые max_sort_length байтов (по умолчанию 1024). Это можно изменить с помощью опции -O max_sort_length для mysqld . Обходной путь для большинства случаев заключается в использовании подстроки: SELECT DISTINCT LEFT(blob,2048) FROM tbl_name .
В сервере MySQL вычисления производятся в форматах типов BIGINT или DOUBLE (оба типа обычно имеют длину 64 бита). Это зависит от того, какую точность обеспечивает применяемая функция. Общее правило состоит в том, что битовые функции работают с точностью BIGINT , функции IF и ELT() - с точностью BIGINT или DOUBLE , а остальные - с точностью DOUBLE . Следует избегать применения беззнаковых величин двойной точности, если они могут превысить 63 бита (9223372036854775807), для каких-либо величин, кроме битовых полей! В версии сервера MySQL 4.0 реализована лучшая обработка BIGINT , чем в 3.23.
Во всех строковых столбцах, исключая BLOB и TEXT при извлечении данных автоматически удаляются все концевые пробелы. Для типов CHAR это хорошо и может рассматриваться как свойство, соответствующее ANSI SQL92. Ошибка заключается в том, что в сервере MySQL столбцы VARCHAR трактуются тем же самым образом.
В одной таблице может быть только до 255 столбцов типа ENUM и SET .
В MIN() , MAX() и других групповых функциях, MySQL сейчас сравнивает ENUM и SET -столбцы по их строковому значению, а не по относительной позиции строки в множестве.
При указании параметра safe_mysqld все сообщения из mysqld направляются в журнал данного потока mysqld . Одна из проблем заключается в том, что если вы исполняете mysqladmin refresh для того, чтобы закрыть и заново открыть журнал, то stdout и stderr будут все еще по-прежнему направлены в старый журнал. При активном использовании --log следует отредактировать safe_mysqld , чтобы записи велись в "hostname'.err", а не в "hostname'.log", с тем, чтобы вы могли очищать пространство, удаляя старые журналы и вызывая mysqladmin refresh .
При выполнении команды UPDATE столбцы обновляются слева направо. При ссылке на обновленный столбец вместо исходной величины будет получена обновленная величина. Например:
mysql> UPDATE tbl_name SET KEY=KEY+1,KEY=KEY+1;
Эта команда обновит KEY со значением 2 вместо значения 1.
В одном и том же запросе нельзя использовать временные таблицы более чем один раз. Например, следующая команда выполнена не будет:
mysql> SELECT * FROM temporary_table, temporary_table AS t2;
RENAME не работает с временными таблицами или при использовании таблицы MERGE .
Оптимизатор может обрабатывать 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 , что не разрешается делать в ANSI SQL.
Поскольку сервер MySQL обеспечивает возможность работать с типами таблиц, которые не поддерживают транзакции и, следовательно, не допускают отката данных, то поведение сервера MySQL в некоторых аспектах отличается от других серверов SQL. Это делается, чтобы гарантировать, что сервер MySQL никогда не будет нуждаться в откате SQL-команд. Такое поведение временами может быть несколько неудобным, так как вследствие этого величины столбцов должны проверяться в приложении. Однако благодаря такому решению вы получаете действительно хорошее увеличение скорости, поскольку для сервера MySQL обеспечивается возможность производить определенные оптимизации, что в противном случае было бы очень трудно сделать. При попытке установить столбец в некорректную величину сервер MySQL вместо выполнения отката будет сохранять в данном столбце ''наиболее вероятную величину"":
При попытке сохранить в числовом столбце величину, выходящую за допустимые пределы, сервер MySQL вместо нее будет сохранять в этом столбце наименьшую или наибольшую допустимую величину.
При попытке сохранить в числовом столбце строку, которая начинается не с числа, сервер MySQL будет сохранять в нем 0.
При попытке сохранить NULL в числовом столбце, который не принимает значения величины NULL , сервер MySQL вместо NULL будет сохранять 0 или "" (пустая строка) (однако это поведение можно изменить с помощью опции компиляции -DDONT_USE_DEFAULT_FIELDS ).
MySQL обеспечивает возможность сохранять некоторые ошибочные величины даты в столбцах DATE и DATETIME (такие как 2000-02-31 или 2000-02-00). Идея заключается в том, что задача проверки валидности даты не входит в круг обязанностей сервера баз данных. Если MySQL может сохранить и корректно воспроизвести какие-либо значение даты, пусть и неправильное - MySQL будет сохранять такое значение. Если дата полностью неправильна, сервер MySQL будет сохранять в этом столбце специальную величину даты 0000-00-00.
Если устанавливать столбец ENUM в неподдерживаемую величину, то он будет устанавливаться в значение ошибки empty string с числовым значением 0.
Если устанавливать столбец SET в неподдерживаемую величину, то эта величина будет игнорироваться.
При выполнении PROCEDURE на запросе, возвращающем пустой набор, в некоторых случаях PROCEDURE не будет преобразовывать столбцы.
При создании таблицы типа MERGE не происходит проверки, если лежащие в ее основе таблицы имеют совместимые типы.
Сервер MySQL пока еще не может обрабатывать величины NaN , -Inf и Inf с двойной точностью. Их использование вызовет проблемы при попытке экспорта или импорта данных. В качестве промежуточного решения мы должны изменить NaN на NULL (если возможно) и -Inf и Inf на минимальную или, соответственно, максимально возможную величину двойной точности.
LIMIT на отрицательных числах трактуются как большие положительные числа.
Если ALTER TABLE используется для того, чтобы сначала добавить индекс UNIQUE к таблице, которая входит в таблицу MERGE , а затем - чтобы добавить обычный индекс к таблице MERGE , то в случае, если существовал старый ключ, который не был уникальным в данной таблице, порядок ключей для таблиц будет различным. Это обусловлено тем, что ALTER TABLE помещает уникальные ключи перед обычными ключами, чтобы обеспечить возможность определять дублирующиеся ключи как можно раньше.
В более ранних версиях MySQL известны следующие ошибки:
Можно получить зависший поток при выполнении DROP TABLE на таблице, которая является одной из числа многих таблиц, заблокированных с помощью LOCK TABLES .
В следующем случае может произойти аварийное завершение процесса:
В версиях сервера MySQL до 3.23.2 команда UPDATE , которая обновляла ключ с помощью WHERE на тот же самый ключ, может оказаться неудачной, поскольку данный ключ использовался для поиска записей и одна и та же строка может быть найдена много раз:
UPDATE tbl_name SET KEY=KEY+1 WHERE KEY > 100;
Обходным решением является использование:
mysql> UPDATE tbl_name SET KEY=KEY+1 WHERE KEY+0 > 100;
Эта команда будет работать, поскольку сервер MySQL не будет использовать индекс на выражениях в утверждении WHERE .
До версии сервера MySQL 3.23 все числовые типы трактовались как поля с фиксированной точкой. Это означает, что необходимо было указывать, сколько десятичных знаков должно содержать поле с плавающей точкой. Все результаты возвращались с правильным количеством десятичных знаков.
В отношении ошибок, связанных со спецификой различных платформ, см. разделы о компилировании и переносе.
1 2 3 4
8 8 8
| |