Тупик в транзакции с сериализуемым уровнем изоляции

Я пытался понять, как работает блокировка с уровнями изоляции. Я рассмотрел этот вопрос, но не могу понять данный поток дуть

Здесь я запускаю две транзакции в разных терминалах и читаю в них одну и ту же строку. Когда я пытаюсь обновить их оба, терминал продолжает ждать обновления. Никакой другой запрос не выполняется, кроме этого

Вот ряд шагов, которые я сделал

conn1: START TRANSACTION;
conn1: SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
conn2: START TRANSACTION;
conn2: SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
conn1: SELECT * from users WHERE id = 1;
conn2: SELECT * from users WHERE id = 1;
conn1: UPDATE users set name = 'name' WHERE id = 1; waiting...
conn2: UPDATE users set name = 'name' WHERE id = 1; waiting...

Вот мой первый вопрос
Здесь я хочу понять, почему оба соединения ждут, и если они есть, у кого есть блокировка для обновления строки?

Если я изменю вышеуказанные шаги на

conn1: START TRANSACTION;
conn1: SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
conn2: START TRANSACTION;
conn2: SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
conn1: UPDATE users set name = 'name' WHERE id = 1;
conn2: SELECT * from users WHERE id = 1; waiting...
conn1: commit
conn2: updated results

В этом случае разница в том, что я вижу, что conn1 имеет блокировку, и пока он не зафиксирует или не откатит изменения, все остальные запросы будут ожидать и получат обновленные результаты, если conn1 зафиксирован

Вот мой второй вопрос
Это правильный способ, если я хочу заблокировать строку, и если она заблокирована, я хочу, чтобы другие соединения ждали (даже для чтения), пока эта блокировка не будет снята (фиксация или откат), или я должен использовать предложение for update

БД — Mysql 5.7


person Mawa    schedule 28.09.2020    source источник
comment
Если это точная копия вашего кода, имеет ли значение опечатка SERIALAZIBLE?   -  person seanb    schedule 29.09.2020
comment
@seanb Извините, это был тип, в реальном запросе это было правильно   -  person Mawa    schedule 29.09.2020
comment
Это все хорошо. Просто исключаю. Я проголосовал за ответ Шэдоу ниже, так как думаю, что он довольно хорошо его описывает.   -  person seanb    schedule 29.09.2020


Ответы (1)


Как документация mysql на SERIALIZABLE уровень изоляции говорит:

Этот уровень похож на REPEATABLE READ, но InnoDB неявно преобразует все простые операторы SELECT в SELECT ... LOCK IN SHARE MODE.

Пункт об автоматической фиксации здесь не применяется, так как вы явно запускаете транзакцию.

Это означает, что в первом сценарии обе транзакции получают общую блокировку одной и той же записи. Затем первая транзакция (T1) пытается выполнить обновление, для которого требуется эксклюзивная блокировка. Это не может быть предоставлено, так как T2 имеет общую блокировку. Затем T2 пытается обновиться, но не может из-за того, что T1 удерживает общую блокировку.

Используете ли вы атомарное обновление или оператор select ... for update для блокировки записей, зависит от логики приложения, которую необходимо применить. Если вам нужно получить данные записи и выполнить с ними сложные вычисления перед обновлением записи, используйте подход select ... for update. В противном случае перейдите на атомарное обновление.

person Shadow    schedule 28.09.2020