这源于这个相关的问题,我想知道如何在一个微不足道的情况下强制两个事务按顺序发生(两个事务都只在一行上运行)。我得到了一个答案——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;
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 被打断走开,忘记结束事务。应用程序会停止,直到行被解锁。我想尽量减少应用程序因这个错误而卡住的时间。
假设我有几个用户同时运行“ruby”进程。如何编写一个 shell 命令来终止一个特定用户的“ruby”进程?(我使用的是 CentOS 5.5。)
假设我有两台服务器同时使用 InnoDB 在 MySQL 5.5 数据库上启动事务。两个事务都做同样的事情:读取一行,然后根据其内容更新该行。我想确保两个事务一个接一个地运行。也就是说,在第一个事务完成之前,不应允许第二个事务读取该行。理想情况下,这意味着SELECT第二个事务中的语句将等到第一个事务提交后,然后返回更新后的值。
这可能吗?如果没有,是否有比 MySQL 更适合此任务的数据库?
如果是这样,一个相关的问题:假设第一台服务器在交易过程中崩溃,所以没有COMMIT收到任何消息。我将如何设置超时后事务将自动回滚,以便第二个事务不会永远延迟?(更新:我已经把它作为一个单独的问题分开了。)