Вы можете добавить FOR UPDATE в оператор выбора, чтобы заблокировать все строки, с которыми он сталкивается.
Но этого недостаточно - в основном вам нужно заблокировать всю таблицу (потому что вы собираетесь обновить всю таблицу), и транзакции не сделают это за вас. В innoDB есть блокировка на уровне строк, и блокируются только нужные строки, что плохо сработает, потому что вы выбираете только одну строку, но обновляете все.
ВЫБОР всей таблицы ДЛЯ ОБНОВЛЕНИЯ, чтобы заблокировать все строки, может заблокировать все, но лучше это будет самый первый запущенный ВЫБОР. В противном случае вы читаете одну строку и замораживаете свое представление (последовательное чтение), затем другая транзакция делает то же самое. Теперь у вас обоих одинаковое представление - но эта вторая транзакция действительно должна прочитать данные, которые вот-вот изменятся! (Вторая транзакция не будет блокироваться - вы читаете и блокируете разные строки. Система не знает, что вы планируете обновить всю таблицу.) Поэтому, если вы заблокируете таким образом (FOR UPDATE), этот оператор должен быть один, чтобы «заморозить» ваш взгляд на стол.
После некоторых исследований я решил, что единственно возможным решением является консультативная блокировка.
(Обычная команда LOCK в MySQL не работает с транзакциями.)
Вместо этого используйте функцию GET_LOCK и запустите ее до открытия транзакции, а не после.
т.е.
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT GET_LOCK('folders_nested_set', <timeout>); /* remember to check to make sure the lock worked */
START TRANSACTION WITH CONSISTENT SNAPSHOT;
do work on folders table here
COMMIT;
DO RELEASE_LOCK('folders_nested_set');
Убедитесь, что все функции, которые работают с вложенным набором, включены в транзакции. Не для записи, но для обеспечения согласованного чтения по операторам SQL.
1020 * т.е. *
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION WITH CONSISTENT SNAPSHOT;
do reads here
COMMIT;
Если вы не знаете, что читаете все необходимые данные в одном выражении SQL, это вам не нужно.
(Вы можете выполнить УСТАНОВИТЬ УРОВЕНЬ ИЗОЛЯЦИИ СЕССИИ С ПОВТОРЯЮЩЕЙСЯ ЧИТАТЬ; сразу после подключения к БД вместо каждой транзакции. В этом случае обязательно включите ключевое слово SESSION.)
Если я ошибаюсь или что-то здесь упустил - или даже если есть лучший способ, я был бы очень признателен, если бы знал об этом, потому что я имею дело именно с этой ситуацией.