Обработка дедлоков в MySql Сергей Париев, Undev.Ru [email_address]
Дедлок - что это такое Неправильная организация доступа к данным + пример Специфика работы блокировок MySql Узнаем больше (SHOW ENGINE INNODB STATUS) Содержание
Что это такое Дедлок - ситуация,  в которой 2 или более процесса ждут друг от друга освобождения занятых ресурсов,  или более двух процессов  ждут ресурсы в циклической порядке (  http://en.wikipedia.org/wiki/Deadlock  )
Что это такое FAIL InnoDB автоматически распознает дедлоки и откатывает одну из транзакций простой пример Транзакция 1 Транзакция 2 select name from events  where  id = 1  for update select name from events where  id = 2  for update select name from events where  id = 2  for update select name from events  where  id = 1  for update
Что это такое Еще более простой пример
Причины дедлоков Неправильная организация доступа к данным  Специфика работы блокировок в БД
Причины дедлоков Отсутствие фиксированного порядка обращения к таблицам и записям Некорректно спроектированная БД  Неправильная организация доступа к данным Неправильная организация доступа к данным
Неправильная организация доступа к данным
Что это такое FAIL Отсутствие фиксированного порядка доступа В порядке возрастания В порядке убывания Неправильная организация доступа к данным Транзакция 1 Транзакция 2 select name from events  where  id = 1  for update select name from events where  id = 2  for update select name from events where  id = 2  for update select name from events  where  id = 1  for update
Порядок доступа все манипуляции с данными лучше проводить в условленном порядке например, в порядке возрастания первичного ключа это снижает вероятность дедлоков Неправильная организация доступа к данным
Отсутствие необходимых индексов Иногда нужно разносить 1 таблицу  на несколько, если она несет слишком много смысловой нагрузки Некорректно  спроектированная БД Неправильная организация доступа к данным
Пример (основан на реальных событиях)
Исходная задача очередь событий (events) много операторов-клиентов, обрабатывающих события в режиме  FIFO (слегка анонимизирована) Пример
Структура данных Индекс по полю locked_at Пример EVENTS id title user_id event_time locked_at ... ... ... ... ...
first_unprocessed, v1 SELECT id AS event_id, ... FROM events  WHERE locked_at IS NULL  OR locked_at < [1.minute.ago] ORDER BY event_time ASC LIMIT 1 FOR UPDATE UPDATE events SET locked_at = [Time.now]  WHERE id = [event_id] Находим первое необработанное событие, “занимаем” его и возвращаем оператору: Пример
touch v1 UPDATE events SET locked_at = [Time.now]  WHERE id = [event_id] Обновляем блокировку, если обработка занимает более одной минуты (event_id получаем от клиента): Пример
DEADLOCK! (Различные пути доступа к данным) Пример first_unprocessed touch index_events_on_locked_at (при выборке  SELECT * ... FOR UPDATE) PRIMARY_KEY (в условии UPDATE) PRIMARY_KEY (при обновлении) index_events_on_locked_at (при обновлении)
touch v2 UPDATE events SET locked_at = [Time.now]  WHERE id = [event_id] Используем результат запроса из first_unprocessed в качестве семафора, после чего обновляем блокировку: SELECT id AS event_id FROM events  WHERE ... FOR UPDATE Пример
Пример
first_unapproved v2 Новое требование:  выбирать события для указанного юзера. В запрос добавляется условие user_id = [user_id] Новая проблема: Для пользователей с малым кол-вом записей MySql использует индекс по user_id (снова различные пути доступа) Решение?  FORCE INDEX index_events_on_locked_at Пример
Проблемы снижение скорости работы при увеличении размеров таблицы конфликты с другими частями приложения, использующими Events Пример
Решение Отдельная таблица для блокировок Записи добавляются/удаляются в Event#after_create/update/destroy  Изменения в структуре БД Пример EVENT_LOCKS id event_id user_id event_time locked_at ... ... ... ... ...
Summary Унифицировать порядок обращения Разнести конфликтующий функционал по разным таблицам Дедлоки,  обусловленные неправильной организацией доступа к данным, можно устранить: Неправильная организация доступа к данным
Специфика работы блокировок в MySql
Причины дедлоков MySql 5.0 InnoDB InnoDB  блокирует не строки таблицы,  а записи индексов (если в таблице нет индексов, InnoDB создает скрытый) специфика работы блокировок MySql Cпецифика работы блокировок MySql
Блокировки в MySql Cпецифика работы блокировок MySql Row Lock Блокировка записи индекса Next-key Lock Row lock + блокировка “промежутка” записей индекса
Row Lock Блокируется только одна запись Используется только при выборке с использованием уникального индекса SELECT name FROM events WHERE id = 3 (id - первичный ключ) Cпецифика работы блокировок MySql
Next-key Lock Next-key Lock =  блокировка записи (Row Lock) + блокировка “промежутка” перед записью Пример Cпецифика работы блокировок MySql (-inf.. 3] (3..5] (5..10] (10..15] (15..+inf)
Next-key Lock используется для предотвращения phantom read Cпецифика работы блокировок MySql Транзакция 1 Транзакция 2 SELECT * FROM events WHERE another_id > 8 FOR UPDATE INSERT INTO events (another_id) VALUES (9) SELECT * FROM events WHERE another_id > 8 FOR UPDATE FAIL 2й запрос возвращает другие данные
Next-key Lock InnoDB блокирует все встреченные записи индекса, используемого в запросе SELECT * FROM events WHERE another_id > 8 FOR UPDATE Cпецифика работы блокировок MySql ... 3 3..5 5..10 10..15 15...
Next-key Lock изменить уровень изоляции на READ COMMITTED включить системную переменную innodb_locks_unsafe_for_binlog Если не используется индекс, InnoDB фактически блокирует все таблицу! Next-key lock можно отключить: (возможен phantom read) Cпецифика работы блокировок MySql
MySql 5.1 меньше блокировок в READ-COMMITTED при DML операциях - блокируются только те строки, которые действительно изменяются более производительная блокировка для AUTO_INCREMENT полей ( подробнее тут -  http://bit.ly/4iF2mu  ) Cпецифика работы блокировок MySql
Проблема Cпецифика работы блокировок MySql Много блокировок + длинная транзакция = много дедлоков
Решение Делаем мало блокировок (правильные индексы) Используем короткие транзакции Cпецифика работы блокировок MySql
Пример 1 better_nested_set не приспособлен к конкурентной модификации дерева - большие транзакции, update по всей таблице has_tree как альтернатива (данные об иерархии хранятся в отдельной таблице) http://github.com/dima-exe/has_tree Cпецифика работы блокировок MySql
Пример 2 counters в has_many update-ы в произвольном порядке, вероятность дедлоков выше при длинных транзакциях альтернатива - вынести счетчики в отдельную таблицу, уменьшить размеры транзакций Cпецифика работы блокировок MySql
Что делать deadlock_retry (  http://github.com/rails/deadlock_retry  ) -  если дедлоков мало LOCK TABLES - блокировки на уровне таблиц (think MyISAM) Использовать READ-COMMITTED (помним о phantom-read) Cпецифика работы блокировок MySql
Summary Используем индексы Короткие транзакции Если дедлоков мало, их можно игнорировать, перезапуская транзакции Cпецифика работы блокировок MySql
Узнаем больше SHOW ENGINE INNODB STATUS
 
Описаны последние 2 транзакции и последние запросы из каждой (не обязательно именно те, которые вызвали дедлок)
Ресурсы http://dev.mysql.com/doc/refman/5.0/en/innodb-deadlocks.html http://www.mysqlperformanceblog.com / (  http://bit.ly/wchKP  ,  http://bit.ly/1Bz0AY  ) http://www.xaprb.com/blog/  (  http://bit.ly/Ldq2t  ,  http://bit.ly/8nRFn  ,  http://bit.ly/8nRFn  ) High Performance MySQL - O’Reilly
 

Сергей Париев - "обработка дедлоков в MySql"

  • 1.
    Обработка дедлоков вMySql Сергей Париев, Undev.Ru [email_address]
  • 2.
    Дедлок - чтоэто такое Неправильная организация доступа к данным + пример Специфика работы блокировок MySql Узнаем больше (SHOW ENGINE INNODB STATUS) Содержание
  • 3.
    Что это такоеДедлок - ситуация, в которой 2 или более процесса ждут друг от друга освобождения занятых ресурсов, или более двух процессов ждут ресурсы в циклической порядке ( http://en.wikipedia.org/wiki/Deadlock )
  • 4.
    Что это такоеFAIL InnoDB автоматически распознает дедлоки и откатывает одну из транзакций простой пример Транзакция 1 Транзакция 2 select name from events where id = 1 for update select name from events where id = 2 for update select name from events where id = 2 for update select name from events where id = 1 for update
  • 5.
    Что это такоеЕще более простой пример
  • 6.
    Причины дедлоков Неправильнаяорганизация доступа к данным Специфика работы блокировок в БД
  • 7.
    Причины дедлоков Отсутствиефиксированного порядка обращения к таблицам и записям Некорректно спроектированная БД Неправильная организация доступа к данным Неправильная организация доступа к данным
  • 8.
  • 9.
    Что это такоеFAIL Отсутствие фиксированного порядка доступа В порядке возрастания В порядке убывания Неправильная организация доступа к данным Транзакция 1 Транзакция 2 select name from events where id = 1 for update select name from events where id = 2 for update select name from events where id = 2 for update select name from events where id = 1 for update
  • 10.
    Порядок доступа всеманипуляции с данными лучше проводить в условленном порядке например, в порядке возрастания первичного ключа это снижает вероятность дедлоков Неправильная организация доступа к данным
  • 11.
    Отсутствие необходимых индексовИногда нужно разносить 1 таблицу на несколько, если она несет слишком много смысловой нагрузки Некорректно спроектированная БД Неправильная организация доступа к данным
  • 12.
    Пример (основан нареальных событиях)
  • 13.
    Исходная задача очередьсобытий (events) много операторов-клиентов, обрабатывающих события в режиме FIFO (слегка анонимизирована) Пример
  • 14.
    Структура данных Индекспо полю locked_at Пример EVENTS id title user_id event_time locked_at ... ... ... ... ...
  • 15.
    first_unprocessed, v1 SELECTid AS event_id, ... FROM events WHERE locked_at IS NULL OR locked_at < [1.minute.ago] ORDER BY event_time ASC LIMIT 1 FOR UPDATE UPDATE events SET locked_at = [Time.now] WHERE id = [event_id] Находим первое необработанное событие, “занимаем” его и возвращаем оператору: Пример
  • 16.
    touch v1 UPDATEevents SET locked_at = [Time.now] WHERE id = [event_id] Обновляем блокировку, если обработка занимает более одной минуты (event_id получаем от клиента): Пример
  • 17.
    DEADLOCK! (Различные путидоступа к данным) Пример first_unprocessed touch index_events_on_locked_at (при выборке SELECT * ... FOR UPDATE) PRIMARY_KEY (в условии UPDATE) PRIMARY_KEY (при обновлении) index_events_on_locked_at (при обновлении)
  • 18.
    touch v2 UPDATEevents SET locked_at = [Time.now] WHERE id = [event_id] Используем результат запроса из first_unprocessed в качестве семафора, после чего обновляем блокировку: SELECT id AS event_id FROM events WHERE ... FOR UPDATE Пример
  • 19.
  • 20.
    first_unapproved v2 Новоетребование: выбирать события для указанного юзера. В запрос добавляется условие user_id = [user_id] Новая проблема: Для пользователей с малым кол-вом записей MySql использует индекс по user_id (снова различные пути доступа) Решение? FORCE INDEX index_events_on_locked_at Пример
  • 21.
    Проблемы снижение скоростиработы при увеличении размеров таблицы конфликты с другими частями приложения, использующими Events Пример
  • 22.
    Решение Отдельная таблицадля блокировок Записи добавляются/удаляются в Event#after_create/update/destroy Изменения в структуре БД Пример EVENT_LOCKS id event_id user_id event_time locked_at ... ... ... ... ...
  • 23.
    Summary Унифицировать порядокобращения Разнести конфликтующий функционал по разным таблицам Дедлоки, обусловленные неправильной организацией доступа к данным, можно устранить: Неправильная организация доступа к данным
  • 24.
  • 25.
    Причины дедлоков MySql5.0 InnoDB InnoDB блокирует не строки таблицы, а записи индексов (если в таблице нет индексов, InnoDB создает скрытый) специфика работы блокировок MySql Cпецифика работы блокировок MySql
  • 26.
    Блокировки в MySqlCпецифика работы блокировок MySql Row Lock Блокировка записи индекса Next-key Lock Row lock + блокировка “промежутка” записей индекса
  • 27.
    Row Lock Блокируетсятолько одна запись Используется только при выборке с использованием уникального индекса SELECT name FROM events WHERE id = 3 (id - первичный ключ) Cпецифика работы блокировок MySql
  • 28.
    Next-key Lock Next-keyLock = блокировка записи (Row Lock) + блокировка “промежутка” перед записью Пример Cпецифика работы блокировок MySql (-inf.. 3] (3..5] (5..10] (10..15] (15..+inf)
  • 29.
    Next-key Lock используетсядля предотвращения phantom read Cпецифика работы блокировок MySql Транзакция 1 Транзакция 2 SELECT * FROM events WHERE another_id > 8 FOR UPDATE INSERT INTO events (another_id) VALUES (9) SELECT * FROM events WHERE another_id > 8 FOR UPDATE FAIL 2й запрос возвращает другие данные
  • 30.
    Next-key Lock InnoDBблокирует все встреченные записи индекса, используемого в запросе SELECT * FROM events WHERE another_id > 8 FOR UPDATE Cпецифика работы блокировок MySql ... 3 3..5 5..10 10..15 15...
  • 31.
    Next-key Lock изменитьуровень изоляции на READ COMMITTED включить системную переменную innodb_locks_unsafe_for_binlog Если не используется индекс, InnoDB фактически блокирует все таблицу! Next-key lock можно отключить: (возможен phantom read) Cпецифика работы блокировок MySql
  • 32.
    MySql 5.1 меньшеблокировок в READ-COMMITTED при DML операциях - блокируются только те строки, которые действительно изменяются более производительная блокировка для AUTO_INCREMENT полей ( подробнее тут - http://bit.ly/4iF2mu ) Cпецифика работы блокировок MySql
  • 33.
    Проблема Cпецифика работыблокировок MySql Много блокировок + длинная транзакция = много дедлоков
  • 34.
    Решение Делаем малоблокировок (правильные индексы) Используем короткие транзакции Cпецифика работы блокировок MySql
  • 35.
    Пример 1 better_nested_setне приспособлен к конкурентной модификации дерева - большие транзакции, update по всей таблице has_tree как альтернатива (данные об иерархии хранятся в отдельной таблице) http://github.com/dima-exe/has_tree Cпецифика работы блокировок MySql
  • 36.
    Пример 2 countersв has_many update-ы в произвольном порядке, вероятность дедлоков выше при длинных транзакциях альтернатива - вынести счетчики в отдельную таблицу, уменьшить размеры транзакций Cпецифика работы блокировок MySql
  • 37.
    Что делать deadlock_retry( http://github.com/rails/deadlock_retry ) - если дедлоков мало LOCK TABLES - блокировки на уровне таблиц (think MyISAM) Использовать READ-COMMITTED (помним о phantom-read) Cпецифика работы блокировок MySql
  • 38.
    Summary Используем индексыКороткие транзакции Если дедлоков мало, их можно игнорировать, перезапуская транзакции Cпецифика работы блокировок MySql
  • 39.
    Узнаем больше SHOWENGINE INNODB STATUS
  • 40.
  • 41.
    Описаны последние 2транзакции и последние запросы из каждой (не обязательно именно те, которые вызвали дедлок)
  • 42.
    Ресурсы http://dev.mysql.com/doc/refman/5.0/en/innodb-deadlocks.html http://www.mysqlperformanceblog.com/ ( http://bit.ly/wchKP , http://bit.ly/1Bz0AY ) http://www.xaprb.com/blog/ ( http://bit.ly/Ldq2t , http://bit.ly/8nRFn , http://bit.ly/8nRFn ) High Performance MySQL - O’Reilly
  • 43.