MySQL回滚连接丢失/断开的事务



我需要让MySQL服务器在其客户端断开连接后立即回滚事务,因为每个客户端都是并发工作的。这个问题可以像这样重现(使用innodb表类型)

客户端A:

START TRANSACTION;
SELECT MAX(ID) FROM tblone FOR UPDATE;
#... then disconnect your connection to the server

客户端B:

START TRANSACTION;
SELECT MAX(ID) FROM tblone FOR UPDATE;
#... lock wait time out will occur here

我设置了MySQL的服务器选项innodb_rollback_on_timeout,并在两个客户端上使用MySQL的客户端mysql --skip-reconnect。我在网络上使用了一台服务器和两台客户端进行了尝试。我在SELECT ... FOR UPDATE;线路后物理断开了网络连接(拔下电缆)。我需要让其他客户端能够立即在事务上使用tblone(锁定、更新),为此,我认为服务器应该在客户端a断开连接后回滚客户端a的事务。

当您物理断开客户端时,您不会发送正常的断开连接(这会导致回滚),MySQL协议也不太好聊天,因此服务器永远不会知道客户端不在。与其他数据库系统相比,我认为这是协议中的一个缺陷,在其他数据库系统中,客户端和服务器的内部对话要多得多。

不管怎样。有两个变量可以更改。他们基本上都是一样的,但针对不同的客户。

第一个是wait_timeout,它由java或php等应用程序客户端使用。

另一个是interactive_timeout,它由mysql客户端使用(就像在测试中一样)

在这两种情况下,服务器都会在几秒钟后终止连接,并在这样做时回滚所有事务并释放所有锁。

这是为了讨论一些注释。请注意,这与部分意见不一致。我将使用INSERT而不是SELECT。。FOR UPDATE,因为效果更明显。

让我们来看一些不同的案例:

(1) 无SQL+超时

START TRANSACTION;
do some SQL statement(s)
do no SQL for more than the timeout (before COMMITing)

由于下面详细介绍的情况,请避免这种情况。解决方案:不要依赖InnoDB来帮助您处理长事务。

(2) 长时间查询

START TRANSACTION;
do some SQL statement(s)
run an SQL query that takes more than the timeout
COMMIT;

一切都很好。只要服务器(mysqld)继续执行查询,超时就不适用。也就是说,超时"时钟"从每个SQL语句的末尾开始

(3) (自动重新连接)

START TRANSACTION;
INSERT ... VALUES (123);
    time passes; no SQL performed for longer than the timeout
    disconnect occurs
INSERT ... VALUES (456);
    auto-reconnect (because you have it ENabled);
    the INSERT proceeds
COMMIT;

123将被回滚;456将被插入。(类似地,SELECT..FOR UPDATE会丢失锁。)不好。解决方案是关闭";自动重新连接";。相反,检查错误并将断开连接错误视为事务的致命错误。(然后重新开始交易。)

INSERT 456将在由autocommit控制的新事务中运行。

(4) (无自动重新连接)

START TRANSACTION;
INSERT ... VALUES (123);
    time passes; no SQL for longer than the timeout
    disconnect occurs
INSERT ... VALUES (456);
    NO auto-reconnect (because you have it DISabled)
COMMIT;

123将被回滚。456的INSERT将得到一个类似于"插入"的错误;连接丢失";。重新开始交易。

相关内容

  • 没有找到相关文章

最新更新