Це випливало з цього пов'язаного питання , де я хотів знати, як змусити дві транзакції послідовно відбуватися в тривіальному випадку (де обидва працюють лише в одному рядку). Я отримав відповідь - використовуйте SELECT ... FOR UPDATE
як перший рядок обох транзакцій - але це призводить до проблеми: Якщо перша транзакція ніколи не вчиняється або відкочується, то друга транзакція буде заблокована на невизначений термін. innodb_lock_wait_timeout
Змінні задає число секунд , після чого клієнт намагається зробити другу операцію б сказав « До жаль, спробуйте ще раз» ... але наскільки я можу сказати, що вони не були б спробувати ще раз до наступного перезавантаження сервера. Тому:
- Напевно, повинен бути спосіб примусити,
ROLLBACK
якщо транзакція береться назавжди? Повинен я вдатися до використання демона для вбивства таких транзакцій, і якщо так, як би виглядав такий демон? - Якщо з'єднання припинено через
wait_timeout
або вinteractive_timeout
середині транзакції, транзакція відмовляється назад? Чи є спосіб перевірити це з консолі?
Уточнення : innodb_lock_wait_timeout
встановлює кількість секунд, які транзакція чекатиме звільнення блокування перед відмовою; те, що я хочу, - це спосіб примусити звільнити замок.
Оновлення 1 : Ось простий приклад, який демонструє, чому innodb_lock_wait_timeout
недостатньо для того, щоб друга транзакція не була заблокована першою:
START TRANSACTION;
SELECT SLEEP(55);
COMMIT;
Якщо за замовчуванням встановлено значення innodb_lock_wait_timeout = 50
, ця операція завершиться без помилок через 55 секунд. І якщо ви додасте UPDATE
перед SLEEP
рядком, а потім ініціюєте другу транзакцію від іншого клієнта, який намагається виконати SELECT ... FOR UPDATE
той самий рядок, це друга операція, яка вичерпується, а не та, яка заснула.
Що я шукаю - це спосіб змусити припинити спокійний сон цієї транзакції.
Оновлення 2 : У відповідь на занепокоєння hobodave щодо того, наскільки реалістичним є наведений вище приклад, ось альтернативний сценарій: DBA підключається до живого сервера та працює
START TRANSACTION
SELECT ... FOR UPDATE
де другий рядок блокує рядок, до якого часто записує додаток. Потім DBA переривається і відходить, забуваючи закінчити транзакцію. Додаток перемелюється до зупинки, поки рядок не розблокується. Я хотів би мінімізувати час, коли програма застрягла внаслідок цієї помилки.
ROLLBACK
першою транзакцією, якщо на її виконання піде більше n
секунд. Чи можна це зробити?
MYSQL
не має конфігурації, щоб запобігти цьому сценарію. Тому що це неприйнятно зависання сервера через безвідповідальність клієнтів. Я не знайшов жодних труднощів зрозуміти ваше запитання, також це так актуально.