mysql事务未commit
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql事务未commit相关的知识,希望对你有一定的参考价值。
参考技术A 如果一个连接中开启事务且未显式提交或回滚,在不考虑其他因素的前提下,确实应该是只有在连接断开的时候才会回滚。如果出现锁等待,则是根据innodb_rollback_on_timeout参数进行下一步动作,如果此参数是off,则会回滚上一条语句,不会提交或回滚,直到显式提交或回滚(事务一直存在,直到连接断开)。如果此参数是on,在超时后会回滚整个事务。
方法一:
通过以上可看出线程id为4一直未提交,事务开始的时间为2022-02-08 15:08:07。
方法二:通过 show engine innodb status
其中有一段关于事务的描述
从以上也可以看出线程id号为4的事务一直未提交。
方法一:如果能知道哪个用户在执行这个操作,让他提交一下(这种可能性很小)。
方法二:kill掉这个线程id号,让事务回滚。
MySQL Transaction--查看未提交事务执行的SQL
未提交事务
长期未提交事务,指开启事务后,长时间未向MySQL发出SQL执行请求或事务处理(COMMIT/ROLLBACK)请求,在系统表`information_schema`.`INNODB_TRX` 中状态为RUNNING,而在`information_schema`.`PROCESSLIST`中状态为SlEEP。
## 查看未提交的事务(3秒内未操作的事务) SELECT p.ID AS conn_id, P.USER AS login_user, P.HOST AS login_host, p.DB AS database_name, P.TIME AS trx_sleep_seconds, TIME_TO_SEC(TIMEDIFF(NOW(),T.trx_started)) AS trx_open_seconds, T.trx_started, T.trx_isolation_level, T.trx_tables_locked, T.trx_rows_locked, t.trx_state, p.COMMAND AS process_state FROM `information_schema`.`INNODB_TRX` t INNER JOIN `information_schema`.`PROCESSLIST` p ON t.trx_mysql_thread_id=p.id WHERE t.trx_state=‘RUNNING‘ AND p.COMMAND=‘Sleep‘ AND P.TIME>3 ORDER BY T.trx_started ASC \G
导致事务长期未提交的因素很多,常见的有:
1、事务过程中执行其他非数据库操作,导致事务长期未被处理。 2、事务处理异常或实现逻辑有误,导致事务未被正常处理。 3、网段异常导致应用端请求未被正常发送给数据库,数据库等待应用后续操作。 4、应用服务器性能问题(如CPU爆满),导致应用无法及时切换到该进程进行处理。
对于代码实现逻辑有误的问题,如果DBA能提供该事务执行的SQL语句将有助于研发快递定位,哪如何定位呢?
方式1:使用通用日志
## 查看general log配置 show variables like ‘%general_log%‘ ## 开启general log SET GLOBAL general_log = 1;
在通用日志中能看到
2019-04-29T13:52:07.932646+08:00 20036 Query SELECT * FROM `sys`.`processlist` 2019-04-29T13:52:36.049694+08:00 20036 Query SELECT * FROM `sys`.`processlist` WHERE CONN_ID=2036 2019-04-29T13:52:44.378687+08:00 20036 Query SELECT * FROM `sys`.`processlist` WHERE CONN_ID=20040 2019-04-29T13:52:51.418669+08:00 20036 Query SELECT * FROM `sys`.`processlist` WHERE CONN_ID=20040
上面的20036是会话连接号(connection id), 使用SHOW PROCESSLIST 或`information_schema`.`PROCESSLIST`查到的ID即该ID。
对于MySQL 5.7版本,可以使用sys.session视图来查看会话最后一次执行的SQL:
SELECT * FROM sys.session WHERE CONN_ID = 20036 \G
输出结果为:
thd_id: 20065 conn_id: 20040 user: [email protected]172.28.37.35 db: demodb command: Sleep state: NULL time: 19 current_statement: NULL statement_latency: NULL progress: NULL lock_latency: 157.00 us rows_examined: 110 rows_sent: 110 rows_affected: 0 tmp_tables: 0 tmp_disk_tables: 0 full_scan: YES last_statement: select * from tb001 limit 110 last_statement_latency: 607.34 us current_memory: 0 bytes last_wait: NULL last_wait_latency: NULL source: NULL trx_latency: NULL trx_state: NULL trx_autocommit: NULL pid: 12758 program_name: mysql
使用系统视图sys.processlist 也能看到类似上面的结果:
SELECT * FROM sys.processlist WHERE CONN_ID = 20040
系统视图sys.processlist中数据主要来源于:
performance_schema.events_statements_current
performance_schema.events_statements_history
且上面两个表中记录的数据需要使用线程号(THREAD ID),可以使用performance_schema.threads来与连接号(CONNECTION ID/PROCESSLIST ID)进行关联。
因此可以将查询未提交事务的SQL优化为:
## 查看未提交的事务(3秒内未操作的事务) SELECT p.ID AS conn_id, P.USER AS login_user, P.HOST AS login_host, p.DB AS database_name, P.TIME AS trx_sleep_seconds, TIME_TO_SEC(TIMEDIFF(NOW(),T.trx_started)) AS trx_open_seconds, T.trx_started, T.trx_isolation_level, T.trx_tables_locked, T.trx_rows_locked, t.trx_state, p.COMMAND AS process_state, ( SELECT GROUP_CONCAT(T1.`SQL_TEXT` SEPARATOR ‘; ‘) FROM performance_schema.events_statements_history AS T1 INNER JOIN performance_schema.threads AS T2 ON T1.`THREAD_ID`=T2.`THREAD_ID` WHERE T2.`PROCESSLIST_ID`=P.id ) AS trx_sql_text FROM `information_schema`.`INNODB_TRX` t INNER JOIN `information_schema`.`PROCESSLIST` p ON t.trx_mysql_thread_id=p.id WHERE t.trx_state=‘RUNNING‘ AND p.COMMAND=‘Sleep‘ AND P.TIME>3 ORDER BY T.trx_started ASC \G
输出结果中trx_sql_text即该事务执行过的SQL语句。
以上是关于mysql事务未commit的主要内容,如果未能解决你的问题,请参考以下文章