Пример блокировки уровня строки MySQL

Я видел много постов, объясняющих использование Select FOR UPDATE и как заблокировать строку, однако я не смог найти ни одного, объясняющего, что происходит, когда код пытается прочитать заблокированную строку.

Например. Скажем, я использую следующее:

$con->autocommit(FALSE);
$ps = $con->prepare( "SELECT 1 FROM event WHERE row_id = 100 FOR UPDATE");
$ps->execute();
...
//do something if lock successful
...
$mysqli->commit();

В этом случае, как определить, была ли моя блокировка успешной? Каков наилучший способ обработки сценария, когда строка уже заблокирована?

Извините, если это где-то описано, но все, что мне кажется, это объяснения «счастливого пути».

3

Решение

В этом случае, как определить, была ли моя блокировка успешной? Каков наилучший способ обработки сценария, когда строка уже заблокирована?

Если ряд вы пытаясь закрывать является уже заблокирован — сервер MySQL не будет возвращать никакого ответа для этой строки. Он будет ждать², пока транзакция блокировки не будет зафиксирована или откатана.

(Очевидно: если строка уже была удалена, ваш SELECT вернет пустой набор результатов и ничего не заблокирует)

После этого он вернет последнее значение, зафиксированное транзакцией, которая удерживала блокировку.

регулярное Select Заявления не будут заботиться о блокировке и вернуть ток значение, игнорируя, что есть незафиксированное изменение.

Итак, другими словами: ваш код будет выполняться только тогда, когда блокировка прошла успешно. (Другое ожидание², пока не будет снята предыдущая блокировка)

Обратите внимание, что с помощью FOR UPDATE также заблокирует любой транзакционные выборы на время заблокирован — если вы не хотите этого, вы должны использовать LOCK IN SHARE MODE вместо. Это позволит транзакционным выборам перейти к ток значение, при этом просто блокируя любое обновление или удаление оператора.

² запрос вернет ошибку по истечении времени, определенного с innodb_lock_wait_timeout http://dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html#sysvar_innodb_lock_wait_timeout
Потом вернется ОШИБКА 1205 (HY000): превышено время ожидания блокировки; попробуйте перезапустить транзакцию

Другими словами: это точка, в которой ваша попытка получить блокировку не удалась.


Sidenode: этот вид блокировки просто подходит для обеспечения целостности данных. (То есть ни одна строка, на которую ссылаются, не удаляется, пока вы вставляете что-то, ссылающееся на эту строку).

Как только блокировка снята, любая блокируется (или лучше позвоните задерживается) оператор delete будет выполнен, возможно, удалит только что вставленную строку из-за Cascading в ряду, на котором вы только что держали замок, чтобы обеспечить целостность.

Если вы хотите создать систему, чтобы 2 пользователя не изменяли одни и те же данные одновременно, вы должны сделать это на уровне приложения и посмотреть на пессимистический против оптимистичный блокировка подходит, потому что не стоит поддерживать транзакции в течение длительного периода времени. (Я думаю, что в PHP ваши соединения с базой данных автоматически закрываются после каждого запроса в любом случае, вызывая неявную фиксацию для любой запущенной транзакции)

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]