Примера отборного замка в общем режиме, взятом из MySQL documentation:блокировки строк, если выполнение программы прерываются после выбора замка в общем режиме
В качестве примера ситуации, в которой запирающее чтение полезно, предположит, что вы хотите вставьте новую строку в дочерний элемент таблицы и убедитесь, что дочерняя строка имеет родительскую строку в родительской таблице. Предположим, что вы используете последовательное чтение для чтения родительского стола и действительно видите родительскую строку дочерней строки, которая должна быть вставлена в таблицу. Можете ли вы безопасно вставить дочернюю строку в дочерний стол? Нет, потому что для некоторых других сеансов можно удалить родительскую строку из родительского стола тем временем, не зная об этом.
Решение состоит в том, чтобы выполнить ВЫБОР в режиме с использованием блокирующего замка в SHARE MODE:
<?php
DB::query("start transaction");
$q = DB::query("SELECT parentID FROM parent WHERE NAME = 'Jones'
LOCK IN SHARE MODE;");
if(count($q) === 1)
DB::query("insert into child set parentName = 'Jones', ... other data");
DB::query("commit;");
?>
SELECT ... LOCK IN SHARE MODE задает общую блокировку режима на любых строк, которые считываются. Другие сеансы могут считывать строки, но не могут изменять их до момента совершения транзакции.
Что происходит, если выполнение кода не выполняется (ошибки php, ошибки операционной системы, сбой питания, ...) сразу после выполнения запроса начать транзакцию; выберите parentID из родителя, где name = 'Jones' режим блокировки в режиме общего доступа;. Как долго фиксируется строка для обновления и удаления? Я хочу убедиться, что даже если выполнение не удастся, эта строка не останется заблокированной (скажем, что PHP не удался, но MySQL все еще работает). Как MySQL обрабатывает эту ситуацию. Я полагаю, что в худшем случае таймаут происходит следующим образом:
ОШИБКА 1205 (HY000): превышено время ожидания блокировки; попробуйте перезапустить транзакцию
и MySQL разблокирует заблокированные строки. Или есть лучший механизм.
Я предполагаю, что есть опечатка perior -> период и MySqb -> MySql. – broadband