среда, 29 января 2014 г.

Немного о блокировках в хранимых процедурах MYSQL

Возникла необходимость вызывать одну и туже хранимую процедуру MYSQL из разных процессов. И невольно задумался о синхронизации средствами самой СУБД. Вот, что я раскопал:

Стандартные LOCK_TABLE() внутри хранимых процедур вызывать нельзя.

Транзакции (START TRANSACTION) сами блокировки не ставят, так что просто создать innodb таблицу не поможет =)

Есть такой вариант : SELECT ... FOR UPDATE. Он блокирует только строки, которые прочитал до дальнейшего UPDATE. Этот UPDATE должен быть в пределах этой же транзакции, иначе будут проблемы (блокировка не снимется, насколько я понял)

Подошедший мне вариант был такой:  GET_LOCK(name, timeout) и RELEASE_LOCK(name).
Работает это все по принципу мутексов. Успешная блокировка возвращает 1, т.е.
SELECT SET_LOCK("my_lock", 10);
 -> 1
Если вернулся 0 - значит заблокировал кто-то другой и таймаут истек. А если вообще NULL - то произошла ошибка.
name - задается строкой.
SELECT RELEASE_LOCK("my_lock") вернет 1, если успешно снял блокировку, 0 - если не смог, потому что ее выставил другой поток и NULL - если такой блокировки нет (например, уже сняли, или таймаут истек.)

Для работы с RELEASE_LOCK неплохо подходит оператор DO
DO RELEASE_LOCK("my_lock");
В отличие от SELECT он просто не вернет результат который очень часто от RELEASE и не требуется.

Проверить наличие блокировок можно функциями IS_FREE_LOCK(nameи IS_USED_LOCK(name).
Принцип возврата - такой же. 1 - если ответ "да", 0 - если "нет" и NULL - если такой блокировки вообще не найдено.

Источник информации - документация :)

Комментариев нет:

Отправить комментарий