【问题标题】:Display open transactions in MySQL在 MySQL 中显示打开的事务
【发布时间】:2011-09-29 13:54:05
【问题描述】:

我做了一些没有提交的查询。然后应用程序被停止。

如何显示这些未结交易并提交或取消它们?

【问题讨论】:

  • 我认为您的所有交易都在断开连接后被取消,但不是 100% 确定。
  • 您使用的是什么类型的表格? MyISAM、InnoDB 等?
  • @cdeszaq,显然不是 MyISAM 它没有事务,此外问题真的与表无关。
  • @Johan - 我只给出了 MyISAM 作为表类型的一个例子。这非常确实很重要,因为并非所有支持事务的表在连接丢失事务方面的行为方式都相同。
  • @cdeszaq,MySQL 文档声明了一些非常不同的东西。

标签: mysql


【解决方案1】:

如何显示这些未结交易并提交或取消它们?

没有打开的事务,MySQL会在断开连接时回滚事务。
您不能提交事务 (IFAIK)。

您使用显示线程

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,它与问题有关。应用程序通常使用mysqld.dllAKA 客户端并且您将包含完整事务的SQL语句保留在内存中,以便您可以在连接断开时播放它.或者您将其保存在本地磁盘上,以便在重新启动时重新提交。
  • SHOW FULL PROCESSLIST 中只显示了我的进程列表命令。所以我猜只是没有未结交易。有趣的是,autoincrement_ids 似乎丢失了。
  • @alex 官方文档说明了这一点,因此这是记录在案的行为。查看链接。
  • 漂亮,约翰。回答了这个问题,并展示了一些后果以及这些后果的解决方案,所有这些都在几段之内。
【解决方案2】:

虽然本案中不会有任何剩余交易,正如@Johan 所说,您可以根据需要通过下面的查询查看 InnoDB 中的当前交易列表。

SELECT * FROM information_schema.innodb_trx\G

来自the document

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

【讨论】:

  • 不认为有任何方法可以判断该表中的事务是否属于您的特定请求/会话?
  • 请注意,末尾的\G 修饰符仅在您想在mysql CLI 工具中格式化查询输出时才有用。如果你使用Mysql Workbench之类的GUI工具,就不需要了。
  • @CaptainHypertext trx_mysql_thread_id 列对应full processlist中的连接ID
【解决方案3】:

您可以使用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

【讨论】:

  • 实际上没有必要在超时后主动终止连接,无论如何连接都会被终止,并且无法提交来自断开连接的待处理事务,因此可以重新提交它们而不必担心重复。
  • 最好在不等待超时清理的情况下终止卡住的事务 - 否则您将面临死锁的风险。
  • 啊,是的,+1 评论。一分钟忘记那些死锁。
  • @MarcB,他们为什么把它改成show engine innodb status
【解决方案4】:

通过使用此查询,您可以查看所有未结交易。

列出所有:

SHOW FULL PROCESSLIST  

如果你想杀死一个挂起的事务,复制事务 id 并使用这个命令杀死事务:

KILL <id>    // e.g KILL 16543

【讨论】:

    猜你喜欢
    • 2011-07-19
    • 1970-01-01
    • 2022-01-23
    • 2016-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-16
    • 2011-02-12
    相关资源
    最近更新 更多