B.3.7 Известные проблемы в MySQL
В этом разделе перечислены известные проблемы в последних версиях MySQL.
Сведения о проблемах, связанных с конкретной платформой, см. в руководстве по установке и отладке в разделе 2.1, «Общие рекомендации по установке», и разделе 5.8, «Отладка MySQL».
Известны следующие проблемы:
Оптимизация подзапросов для
INне так эффективна, как для=.Даже если вы используете
lower_case_table_names=2(что позволяет MySQL запоминать регистр, используемый для баз данных и имён таблиц), MySQL не запоминает регистр имён баз данных для функцииDATABASE()или в различных логах (на системах с регистронезависимым режимом).Удаление ограничения
FOREIGN KEYне работает в репликации, потому что это ограничение может иметь другое имя на реплике.REPLACE(иLOAD DATAс опциейREPLACE) не запускаетON DELETE CASCADE.DISTINCTсORDER BYне работает внутриGROUP_CONCAT(), если вы не используете все и только те столбцы, которые находятся в спискеDISTINCT.При вставке большого целого значения (между 263 и 264−1) в столбец типа decimal или string, оно вставляется как отрицательное значение, потому что число оценивается в контексте целого со знаком.
-
При использовании журналов двоичных логов на основе инструкций, сервер-источник записывает выполненные запросы в двоичный журнал. Это очень быстрый, компактный и эффективный метод протоколирования, который идеально работает в большинстве случаев. Однако возможно, что данные на источнике и реплике станут разными, если запрос разработан таким образом, что изменение данных не является детерминированным (обычно не рекомендуемая практика, даже вне репликации).
Например:
инструкции
CREATE TABLE ... SELECTилиINSERT ... SELECT, которые вставляют нулевые илиNULLзначения в столбец типаAUTO_INCREMENT.DELETE, если вы удаляете строки из таблицы, которая имеет внешние ключи сON DELETE CASCADEсвойствами.REPLACE ... SELECT,INSERT IGNORE ... SELECT, если у вас есть дублированные значения ключей в вставляемых данных.
Только если предыдущие запросы не имеют фрагмента
ORDER BY, гарантирующего детерминированный порядок.Например, для
INSERT ... SELECTбезORDER BY,SELECTможет возвращать строки в другом порядке (что приводит к тому, что строка имеет другой ранг, следовательно, получает другое число в столбцеAUTO_INCREMENT), в зависимости от выбора, сделанного оптимизаторами на источнике и реплике.Запрос оптимизируется по-разному на источнике и реплике только в том случае, если:
Таблица хранится с помощью другого движка хранилища на источнике, чем на реплике. (Можно использовать разные движки хранилища на источнике и реплике. Например, вы можете использовать
InnoDBна источнике, ноMyISAMна реплике, если у реплики меньше свободного места на диске.)Размеры буфера MySQL (
key_buffer_sizeи т. д.) отличаются на источнике и реплике.Источник и реплика работают под разными версиями MySQL, и код оптимизатора отличается между этими версиями.
Эта проблема также может повлиять на восстановление базы данных с помощью mysqlbinlog|mysql.
Наиболее простой способ избежать этой проблемы — добавить фрагмент
ORDER BYк упомянутым выше недетерминированным запросам, чтобы гарантировать, что строки всегда хранятся или изменяются в одном и том же порядке. Использование форматов журналов на основе строк или смешанного формата также избегает этой проблемы. Имена файлов журналов основаны на имени хоста сервера, если вы не указываете имя файла с помощью опции запуска. Чтобы сохранить те же имена файлов журналов, если вы измените имя хоста на что-то другое, необходимо явно использовать такие опции, как
--log-bin=. См. Раздел 5.1.6, «Параметры командной строки сервера». В качестве альтернативы переименуйте старые файлы, чтобы отразить изменение имени хоста. Если это двоичные журналы, вам также необходимо отредактировать файл индекса двоичного журнала и исправить там имена файлов двоичного журнала. (То же самое относится к релейным журналам на реплике.)old_host_name-binmysqlbinlog не удаляет временные файлы, оставшиеся после инструкции
LOAD DATA. См. Раздел 4.6.7, «mysqlbinlog — Утилита для обработки файлов двоичного журнала».RENAMEне работает с таблицами типаTEMPORARYили таблицами, используемыми в таблицеMERGE.При использовании
SET CHARACTER SETвы не можете использовать символы перевода в именах баз данных, таблиц и столбцов.Вы не можете использовать
_или%сESCAPEвLIKE ... ESCAPE.Сервер использует только первые
max_sort_lengthбайтов при сравнении значений данных. Это означает, что значения не могут быть надёжно использованы вGROUP BY,ORDER BYилиDISTINCT, если они различаются только после первыхmax_sort_lengthбайтов. Чтобы обойти эту проблему, увеличьте значение переменной. Значение по умолчанию дляmax_sort_lengthсоставляет 1024 и может быть изменено при запуске сервера или во время выполнения.Численные вычисления выполняются с помощью
BIGINTилиDOUBLE(оба обычно имеют длину 64 бита). Точность, которую вы получите, зависит от функции. Общее правило состоит в том, что битовые функции выполняются с точностьюBIGINT,IF()иELT()с точностьюBIGINTилиDOUBLE, а остальные — с точностьюDOUBLE. Следует избегать использования беззнаковых 64-битных целых чисел, если они приводят к значению большему, чем 63 бита (9223372036854775807), за исключением битовых полей.Вы можете иметь до 255 столбцов типа
ENUMиSETв одной таблице.В функциях
MIN(),MAX()и других агрегатных функциях MySQL в настоящее время сравнивает столбцы типаENUMиSETпо строковому значению, а не по относительному положению строки в наборе.-
В инструкции
UPDATEстолбцы обновляются слева направо. Если вы ссылаетесь на обновлённый столбец, вы получаете обновлённое значение вместо исходного. Например, следующая инструкция увеличиваетKEYна2, а не1:mysql>
UPDATEtbl_nameSET KEY=KEY+1,KEY=KEY+1; -
Вы можете ссылаться на несколько временных таблиц в одном запросе, но вы не можете ссылаться на любую заданную временную таблицу более одного раза. Например, следующее не работает:
mysql>
SELECT * FROM temp_table, temp_table AS t2;ERROR 1137: Can't reopen table: 'temp_table' -
Оптимизатор может обрабатывать
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;Во втором случае вы можете получить две одинаковые строки в наборе результатов (потому что значения в скрытом столбце
idмогут отличаться).Обратите внимание, что это происходит только для запросов, в которых столбцы
ORDER BYне присутствуют в результате. Если вы выполняете
PROCEDUREна запросе, который возвращает пустой набор, в некоторых случаяхPROCEDUREне преобразует столбцы.Создание таблицы типа
MERGEне проверяет, совместимы ли базовые таблицы.
Если вы используете
ALTER TABLEдля добавленияUNIQUEиндекса в таблицу, используемую вMERGEтаблице, а затем добавляете обычный индекс вMERGEтаблицу, порядок ключей в таблицах отличается, если в таблице был старый, не-UNIQUEключ. Это происходит потому, чтоALTER TABLEпомещаетUNIQUEиндексы перед обычными индексами, чтобы как можно раньше обнаруживать дублирующие ключи.
© 2025 Oracle
Licensed under the GPLv2 License.