在 MySQL/InnoDB 中为事务设置时间限制

Tre*_*ham 12 mysql innodb

这源于这个相关的问题,我想知道如何在一个微不足道的情况下强制两个事务按顺序发生(两个事务都只在一行上运行)。我得到了一个答案——SELECT ... FOR UPDATE用作两个事务的第一行——但这会导致一个问题:如果第一个事务从未提交或回滚,那么第二个事务将被无限期阻塞。innodb_lock_wait_timeout变量设置了尝试进行第二次事务的客户端将被告知“对不起,再试一次”的秒数……但据我所知,他们会再试一次,直到下一次服务器重新启动。所以:

  1. ROLLBACK如果交易永远持续下去,肯定有一种方法可以强制执行吗?我是否必须使用守护进程来终止此类事务,如果是这样,那么这样的守护进程会是什么样子?
  2. 如果连接被事务杀死wait_timeoutinteractive_timeout在事务中途终止,事务是否回滚?有没有办法从控制台测试这个?

说明innodb_lock_wait_timeout设置事务在放弃之前等待锁被释放的秒数;我想要的是一种强制释放锁的方法

更新 1:这是一个简单的例子,说明为什么innodb_lock_wait_timeout不足以确保第二个事务不被第一个阻塞:

START TRANSACTION;
SELECT SLEEP(55);
COMMIT;
Run Code Online (Sandbox Code Playgroud)

使用默认设置innodb_lock_wait_timeout = 50,此事务在 55 秒后无错误地完成。如果您UPDATE在该SLEEP行之前添加一个,然后从另一个尝试SELECT ... FOR UPDATE同一行的客户端发起第二个事务,那么超时的是第二个事务,而不是睡着的那个。

我正在寻找的是一种强制结束这笔交易的宁静沉睡的方法。

更新 2:为了回应 hobodave 对上述示例的真实性的担忧,这里有一个替代方案:DBA 连接到实时服务器并运行

START TRANSACTION
SELECT ... FOR UPDATE
Run Code Online (Sandbox Code Playgroud)

其中第二行锁定了应用程序经常写入的一行。然后 DBA 被打断走开,忘记结束事务。应用程序会停止,直到行被解锁。我想尽量减少应用程序因这个错误而卡住的时间。

小智 11

这个帖子的一半以上似乎是关于如何在 ServerFault 上提问。我认为这个问题是有道理的,而且非常简单:如何自动回滚停滞的事务?

如果您愿意终止整个连接,一种解决方案是设置 wait_timeout/interactive_timeout。请参阅/sf/ask/695568961/