8.11.2 Проблемы блокировки таблиц
Таблицы с использованием InnoDB используют блокировку на уровне строк, что позволяет нескольким сессиям и приложениям одновременно читать и записывать в одну и ту же таблицу без ожидания друг друга и получения несогласованных результатов. Для этого движка хранения избегайте использования оператора LOCK TABLES, так как он не обеспечивает дополнительной защиты, но вместо этого снижает конкуретность. Автоматическая блокировка на уровне строк делает эти таблицы подходящими для самых загруженных баз данных с самыми важными данными, а также упрощает логику приложений, так как вам не нужно блокировать и разблокировать таблицы. Следовательно, движок хранения InnoDB является по умолчанию в MySQL.
MySQL использует блокировку таблиц (вместо блокировки страниц, строк или столбцов) для всех движков хранения, кроме InnoDB. Операции блокировки сами по себе не имеют большого накладных расходов. Но поскольку только одна сессия может записывать в таблицу в любой момент времени, для лучшей производительности с другими движками хранения, используйте их в основном для таблиц, которые часто запрашиваются и редко вставляются или обновляются.
Соображения производительности, благоприятствующие InnoDB
При выборе создания таблицы с помощью InnoDB или другого движка хранения, учтите следующие недостатки блокировки таблиц:
Блокировка таблиц позволяет многим сессиям одновременно читать из таблицы, но если сессия хочет записать в таблицу, она должна сначала получить эксклюзивный доступ, что означает, что ей, возможно, придется подождать, пока другие сессии закончат работу с таблицей. Во время обновления все другие сессии, которые хотят получить доступ к этой конкретной таблице, должны ждать, пока обновление не будет завершено.
Блокировка таблиц вызывает проблемы, когда сессия ожидает, потому что диск заполнен, и свободное место должно стать доступным, прежде чем сессия сможет продолжить. В этом случае все сессии, которые хотят получить доступ к проблемной таблице, также переводятся в состояние ожидания, пока не будет освобождено больше места на диске.
Оператор
SELECT, который занимает много времени, не позволяет другим сессиям обновлять таблицу в это время, заставляя другие сессии казаться медленными или невосприимчивыми. Пока сессия ожидает получения эксклюзивного доступа к таблице для обновлений, другие сессии, которые выполняют операторыSELECT, встают в очередь позади нее, снижая конкуретность даже для сессий только чтения.
Обходные решения для проблем производительности блокировки
Следующие пункты описывают некоторые способы предотвращения или уменьшения конфликтов, вызванных блокировкой таблиц:
Рассмотрите возможность переключения таблицы на движок хранения
InnoDB, используяCREATE TABLE ... ENGINE=INNODBво время настройки или используяALTER TABLE ... ENGINE=INNODBдля существующей таблицы. Подробности о данном движке хранения см. в Главе 14, Движок хранения InnoDB.Оптимизируйте операторы
SELECTдля повышения скорости выполнения, чтобы они блокировали таблицы на более короткое время. Для этого может потребоваться создание сводных таблиц.Запустите mysqld с параметром
--low-priority-updates. Для движков хранения, которые используют только блокировку на уровне таблиц (таких какMyISAM,MEMORYиMERGE), это дает всем операторам, которые обновляют (модифицируют) таблицу, более низкий приоритет, чем операторамSELECT. В этом случае второй операторSELECTв приведенном выше сценарии будет выполняться до оператораUPDATE, и не будет ждать завершения первого оператораSELECT.Чтобы указать, что все обновления, выполненные в определённом соединении, должны выполняться с низким приоритетом, установите переменную сервера
low_priority_updatesравной 1.Чтобы присвоить более низкий приоритет определенному оператору
INSERT,UPDATEилиDELETE, используйте атрибутLOW_PRIORITY.Чтобы присвоить более высокий приоритет определенному оператору
SELECT, используйте атрибутHIGH_PRIORITY. См. Раздел 13.2.9, «Оператор SELECT».Запустите mysqld со значением переменной сервера
max_write_lock_countс низким значением, чтобы заставить MySQL временно повышать приоритет всех операторовSELECT, которые ожидают таблицы после определенного количества операций записи в таблицу (например, для операций вставки). Это позволяет операторам чтения блокировать после определенного количества операций записи.Если у вас есть проблемы со смешанными операторами
SELECTиDELETE, опцияLIMITк операторуDELETEможет помочь. См. Раздел 13.2.2, «Оператор DELETE».Использование
SQL_BUFFER_RESULTс операторамиSELECTможет помочь сократить продолжительность блокировки таблицы. См. Раздел 13.2.9, «Оператор SELECT».Разделение содержимого таблицы на отдельные таблицы может помочь, позволяя запросам работать со столбцами в одной таблице, в то время как обновления ограничены столбцами в другой таблице.
Можно изменить код блокировки в
mysys/thr_lock.c, чтобы использовать одну очередь. В этом случае операции записи и чтения будут иметь одинаковый приоритет, что может помочь некоторым приложениям.
© 2025 Oracle
Licensed under the GPLv2 License.