如何在MySQL中显示未完成的事务

114

我在没有提交的情况下进行了一些查询。然后应用程序停止了。

我该如何显示这些未提交的事务并将其提交或取消?


我认为在断开连接时,所有的交易都会被取消,但不能百分之百确定。 - Johan
你使用的是什么类型的表格?MyISAM,InnoDB等等? - cdeszaq
@cdeszaq,显然不是MyISAM,因为它没有事务,此外这个问题与表格无关。 - Johan
2
@Johan - 我只是拿MyISAM作为表类型的例子。这非常重要,因为并不是所有支持事务的表在连接丢失时对事务的行为都相同。 - cdeszaq
@cdeszaq,MySQL文档中说的与此完全不同。 - Johan
5个回答

86

我怎样能够显示这些未完成的事务并进行提交或者取消?

如果没有未完成的事务,MySQL会在断开连接时回滚事务。
你无法提交该事务(据我所知)。

你可以使用以下代码来显示线程:

SHOW FULL PROCESSLIST  

参考: http://dev.mysql.com/doc/refman/5.1/en/thread-information.html

由于无法从断开的连接中提交事务,因此以下内容不会对您有所帮助。

连接断开后会发生什么
根据MySQL文档:http://dev.mysql.com/doc/refman/5.0/en/mysql-tips.html

4.5.1.6.3. 禁用mysql自动重连

如果mysql客户端在发送语句时失去与服务器的连接,则它会立即自动尝试重新连接到服务器并重新发送语句。但是,即使mysql成功重新连接,您的第一个连接也已经结束,并且您之前的所有会话对象和设置都已丢失:临时表、自动提交模式和用户定义的会话变量。另外,任何当前的事务都将回滚

这种行为可能对您很危险,例如,在以下示例中,服务器在第一次和第二次语句之间关闭并重新启动,而您却不知道:

还可以参考: http://dev.mysql.com/doc/refman/5.0/en/auto-reconnect.html

如何诊断和解决这个问题
检查自动重连:

如果发生自动重新连接(例如由于调用mysql_ping()的结果),则没有明确的指示。要检查重新连接,请在调用mysql_ping()之前调用mysql_thread_id()以获取原始连接标识符,然后再次调用mysql_thread_id()以查看标识符是否改变。

确保在客户端中保留您的最后一个查询(事务),以便在需要时可以重新提交它。
并且禁用自动重连模式,因为它会存在一些危险,需要自己实现重新连接,这样当出现连接断开时就能知道,并重新提交该查询。


这与问题无关。这只影响mysql客户端,而OP谈论的是一个通用应用程序,很可能是他自己的应用程序。此外,由于调用应用程序已停止,它如何能够将事务保留在内存中? - cdeszaq
@cdeszaq,这与问题有很大关系。应用程序通常使用mysqld.dll,也称为客户端,并将包含完整事务的SQL语句保存在内存中,以便在连接断开时可以回放它。或者您可以将其保留在本地磁盘上,以便在重新启动时可以重新提交它。 - Johan
在“显示完整进程列表”中,只有我的进程列表命令被显示出来。因此我猜测这里没有正在进行的事务。有趣的是,自增ID似乎已经丢失了。 - Alex
@alex 官方文档指出,这是记录下来的行为。请参考链接。 - Johan
1
美丽的,约翰。他回答了问题,并在几段话中展示了一些后果和解决方案。 - Gerard ONeill
“连接断开时”还是“重新连接时”? - Peter Chaula

78

虽然在这种情况下不会有任何剩余的交易,如@Johan所说,如果您想要查看InnoDB中的当前事务列表,则可以使用以下查询。

SELECT * FROM information_schema.innodb_trx\G

根据文档

INNODB_TRX表中包含有关每个当前在InnoDB内部执行的事务(不包括只读事务)的信息,包括事务是否等待锁定、事务启动时间以及事务正在执行的SQL语句(如果有)。


不过,你有没有办法判断那个表中的事务是否属于你特定的请求/会话? - Captain Hypertext
4
请注意,\G 修饰符仅在您希望在 mysql 命令行工具内格式化查询输出时才有用。如果您使用的是图形用户界面工具,如 Mysql Workbench,则不需要它。 - barell
2
@CaptainHypertext,trx_mysql_thread_id列对应于full processlist中的连接ID。 - Eugene Pankov
1
这对我来说很有效。SHOW FULL PROCESSLIST没有显示我想要的事务,但这个语句显示了正在运行的事务。 - undefined

40
你可以使用show innodb status(或者show engine innodb status,如果是MySQL的新版本)来获取InnoDB引擎中目前处于等待状态的所有操作列表。在输出的大量信息中,会有一些关于事务以及它们正在运行的内部进程ID。
你不能强制提交或回滚这些事务,但是你可以结束运行它们的MySQL进程,这基本上相当于回滚操作。结束进程的同时也会使MySQL清理掉未完结的事务。
以下是你需要查找的内容:
------------
TRANSACTIONS
------------
Trx id counter 0 140151
Purge done for trx's n:o < 0 134992 undo n:o < 0 0
History list length 10
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 0 0, not started, process no 17004, OS thread id 140621902116624
MySQL thread id 10594, query id 10269885 localhost marc
show innodb status
在这种情况下,目前只有一个连接到InnoDB引擎(即我的登录,运行“show”查询)。如果那一行是实际的连接/卡住的事务需要终止,您可以执行“kill 10594”。

没有必要在超时后主动关闭连接,因为连接会自动关闭,而来自断开连接的挂起事务无法提交,因此可以重新提交而不用担心重复。 - Johan
3
最好在等待超时清理之前就杀掉卡住的交易-否则会有死锁的风险。 - Marc B
啊,是的,对那个评论点赞。我一时忘记了那些死锁问题。 - Johan
@MarcB,为什么他们把它改成 show engine innodb status - Pacerier

3

通过使用这个查询,您可以查看所有未完成的交易。

列出所有:

SHOW FULL PROCESSLIST  

如果您想杀掉一个挂起的事务,请复制事务 ID 并使用以下命令杀死该事务:

KILL <id>    // e.g KILL 16543

交易 <> 过程 - Joel Mellon
交易 <> 过程 - undefined

2

使用下面的查询,您可以检查当前有多少个事务正在运行:

mysql> SELECT count(*) FROM information_schema.innodb_trx;
+----------+
| count(*) |
+----------+
|        3 |
+----------+
1 row in set (0.00 sec)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接