Когда в MySQL/InnoDB возникает тупиковая ситуация, она возвращает эту знакомую ошибку:
"Тупик обнаружен при попытке получить блокировку; попробуйте перезапустить транзакцию "
Так что я сделал запись всех запросов, которые входят в транзакцию, чтобы их можно было просто переиздать, если оператор транзакции завершился с ошибкой. Просто.
Проблема. Когда у вас есть запросы, зависящие от результатов предыдущих запросов, это не работает так хорошо.
Например:
START TRANSACTION;
INSERT INTO some_table ...;
-- Application here gets ID of thing inserted: $id = $database->LastInsertedID()
INSERT INTO some_other_table (id,data) VALUES ($id,'foo');
COMMIT;
В этой ситуации я не могу просто переиздать транзакцию, поскольку она была изначально создана. Идентификатор, полученный первым оператором SQL, больше недействителен после того, как транзакция завершилась неудачно, но используется вторым оператором. Между тем, многие объекты были заполнены данными из транзакции, которые затем становятся устаревшими, когда транзакция откатывается назад. Конечно, сам код приложения "откатывается" с базой данных.
Вопрос: как я могу справиться с этими ситуациями в коде приложения? (PHP)
Я принимаю две вещи. Скажите, пожалуйста, если вы думаете, что я на правильном пути:
1) Поскольку база данных не может просто переиздавать транзакцию дословно в любых ситуациях, мое исходное решение не работает и не должно использоваться.
2) Единственный хороший способ сделать это - обернуть любой и весь код выдачи транзакций в свой собственный блок try/catch и попытаться переиздать сам код, а не только SQL.
Спасибо за ваш вклад. Ты жжешь.