MySQL 事务RUNNING状态引发的Transaction timed out: deadline问题

前言:
    朋友说简单的查询导致Transaction timed out: deadline问题,怀疑是数据库表锁了,

1,应用故障描述Deadline问题: 
--- The error occurred in META-INF/ibatis/ITEM_sqlmap.xml.  
--- The error occurred while executing query.  
--- Check the      SELECT      I.ID,        I.SHOP_ID,        I.ITEM_GROUP_ID,        I.ITEM_GROUP_NAME,        I.ITEM_NAME,        I.LIST_PRICE,        I.PL_PRICE,        I.PROTECTION_PRICE,        I.MALL,        I.STAT,        I.LOGISTICS,        I.TYPE,        I.ITEM_CATEGORY_ID,        I.BRAND_ID,        I.BRAND,        I.FAVOUR_NUM,        I.IS_SUBSCRIBE,        I.VOLUME,        I.WEIGHT,        I.INVENTORY,        I.RELEASE_DATE,        I.OFF_REASON,        I.IS_DEL,        I.CREATED_DATE,        I.UPDATED_DATE,        I.SIMPLE_DESCRIPTION,        I.VIRTUAL_BEGIN_DATE,        I.VIRTUAL_END_DATE,        I.SEQ_NUM,        IPC.PICTURE_PATH     FROM ITEM AS I        INNER JOIN ITEM_PICTURE AS IPC       ON I.ITEM_GROUP_ID = IPC.ITEM_GROUP_ID     where I.ID = ? AND IPC.TYPE=‘1‘  AND IPC.IS_DEL=‘0‘   .  
--- Check the SQL Statement (preparation failed).  
--- Cause: org.springframework.transaction.TransactionTimedOutException: Transaction timed out: deadline was Tue Nov 25 13:33:07 CST 2014
at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQueryWithCallback(MappedStatement.java:204)
at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQueryForObject(MappedStatement.java:120)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:518)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:493)
at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForObject(SqlMapSessionImpl.java:106)
at org.springframework.orm.ibatis.SqlMapClientTemplate$1.doInSqlMapClient(SqlMapClientTemplate.java:273)
at org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClientTemplate.java:203)
... 41 more
Caused by: org.springframework.transaction.TransactionTimedOutException: Transaction timed out: deadline was Tue Nov 25 13:33:07 CST 2014
at org.springframework.transaction.support.ResourceHolderSupport.checkTransactionTimeout(ResourceHolderSupport.java:141)
at org.springframework.transaction.support.ResourceHolderSupport.getTimeToLiveInMillis(ResourceHolderSupport.java:130)
at org.springframework.transaction.support.ResourceHolderSupport.getTimeToLiveInSeconds(ResourceHolderSupport.java:114)
at org.springframework.jdbc.datasource.DataSourceUtils.applyTimeout(DataSourceUtils.java:275)
at org.springframework.jdbc.datasource.DataSourceUtils.applyTransactionTimeout(DataSourceUtils.java:257)
at org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy$TransactionAwareInvocationHandler.invoke(TransactionAwareDataSourceProxy.java:244)
at com.sun.proxy.$Proxy324.prepareStatement(Unknown Source)
at com.ibatis.sqlmap.engine.execution.SqlExecutor.prepareStatement(SqlExecutor.java:497)
at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeQuery(SqlExecutor.java:175)
at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.sqlExecuteQuery(MappedStatement.java:221)
at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQueryWithCallback(MappedStatement.java:189)
... 47 more

2,检查Innodb存储引擎状态以及表锁状态
        SHOW ENINGE INNODB STATUS;没有死锁信息以及其它异常信息;去查询系统表INNODB_LOCKS、INNODB_LOCK_WAITS表都为NULL,只有INNODB_TRX表有记录,并且处于长时间RUNNING状态,判断是因为事务没有提交或者回滚的缘故。
mysql> SELECT * FROM `INNODB_TRX`;
+----------+-----------+---------------------+-----------------------+------------------+------------+---------------------+-----------+---------------------+-------------------+-------------------+------------------+-----------------------+-----------------+-------------------+-------------------------+---------------------+-------------------+------------------------+----------------------------+---------------------------+---------------------------+------------------+----------------------------+
| trx_id   | trx_state | trx_started         | trx_requested_lock_id | trx_wait_started | trx_weight | trx_mysql_thread_id | trx_query | trx_operation_state | trx_tables_in_use | trx_tables_locked | trx_lock_structs | trx_lock_memory_bytes | trx_rows_locked | trx_rows_modified | trx_concurrency_tickets | trx_isolation_level | trx_unique_checks | trx_foreign_key_checks | trx_last_foreign_key_error | trx_adaptive_hash_latched | trx_adaptive_hash_timeout | trx_is_read_only | trx_autocommit_non_locking |
+----------+-----------+---------------------+-----------------------+------------------+------------+---------------------+-----------+---------------------+-------------------+-------------------+------------------+-----------------------+-----------------+-------------------+-------------------------+---------------------+-------------------+------------------------+----------------------------+---------------------------+---------------------------+------------------+----------------------------+
| 19183390 | RUNNING   | 2014-11-25 15:39:30 | NULL                  | NULL             |          9 |              940341 | NULL      | NULL                |                 0 |                 0 |                5 |                  1248 |               3 |                 4 |                       0 | READ COMMITTED      |                 1 |                      1 | NULL                       |                         0 |                      9762 |                0 |                          0 | 
| 19183153 | RUNNING   | 2014-11-25 15:36:41 | NULL                  | NULL             |          0 |              940206 | NULL      | NULL                |                 0 |                 0 |                0 |                   376 |               0 |                 0 |                       0 | READ COMMITTED      |                 1 |                      1 | NULL                       |                         0 |                      9411 |                0 |                          0 | 
| 19183139 | RUNNING   | 2014-11-25 15:36:28 | NULL                  | NULL             |          0 |              940238 | NULL      | NULL                |                 0 |                 0 |                0 |                   376 |               0 |                 0 |                       0 | READ COMMITTED      |                 1 |                      1 | NULL                       |                         0 |                      9937 |                0 |                          0 | 
+----------+-----------+---------------------+-----------------------+------------------+------------+---------------------+-----------+---------------------+-------------------+-------------------+------------------+-----------------------+-----------------+-------------------+-------------------------+---------------------+-------------------+------------------------+----------------------------+---------------------------+---------------------------+------------------+----------------------------+
3 rows in set (0.00 sec)

mysql> SELECT * FROM `INNODB_LOCKS`;
Empty set (0.00 sec)

mysql> SELECT * FROM `INNODB_LOCK_WAITS`;
Empty set (0.00 sec)

mysql>

仔细check从中可以看出,没有表锁,没有行锁,没有锁等待,只有事务RUNNING没有提交或者回滚。临时解决办法,kill掉这些事务所在的线程。

3,问题重现,查看事务表记录
mysql> SELECT * FROM `INNODB_TRX`;
+----------+-----------+---------------------+-----------------------+------------------+------------+---------------------+-----------+---------------------+-------------------+-------------------+------------------+-----------------------+-----------------+-------------------+-------------------------+---------------------+-------------------+------------------------+----------------------------+---------------------------+---------------------------+------------------+----------------------------+
| trx_id   | trx_state | trx_started         | trx_requested_lock_id | trx_wait_started | trx_weight | trx_mysql_thread_id | trx_query | trx_operation_state | trx_tables_in_use | trx_tables_locked | trx_lock_structs | trx_lock_memory_bytes | trx_rows_locked | trx_rows_modified | trx_concurrency_tickets | trx_isolation_level | trx_unique_checks | trx_foreign_key_checks | trx_last_foreign_key_error | trx_adaptive_hash_latched | trx_adaptive_hash_timeout | trx_is_read_only | trx_autocommit_non_locking |
+----------+-----------+---------------------+-----------------------+------------------+------------+---------------------+-----------+---------------------+-------------------+-------------------+------------------+-----------------------+-----------------+-------------------+-------------------------+---------------------+-------------------+------------------------+----------------------------+---------------------------+---------------------------+------------------+----------------------------+
| 19196180 | RUNNING   | 2014-11-25 17:41:10 | NULL                  | NULL             |         12 |              942663 | NULL      | NULL                |                 0 |                 0 |                4 |                  1248 |               2 |                 8 |                       0 | READ COMMITTED      |                 1 |                      1 | NULL                       |                         0 |                      9810 |                0 |                          0 | 
+----------+-----------+---------------------+-----------------------+------------------+------------+---------------------+-----------+---------------------+-------------------+-------------------+------------------+-----------------------+-----------------+-------------------+-------------------------+---------------------+-------------------+------------------------+----------------------------+---------------------------+---------------------------+------------------+----------------------------+
1 rows in set (0.00 sec)

mysql>

4,去Slow log和binlog里面分析
去slow log里面看942663线程ID的slow记录,没有找到, 去看binlog里面942663线程ID的DML记录,有如下2条记录:
#141125 17:41:10 server id 230  end_log_pos 118147 CRC32 0x6f2402a1     Query   thread_id=942663        exec_time=0     error_code=0
SET TIMESTAMP=1416908470/*!*/;
BEGIN
/*!*/;
# at 118147
#141125 17:41:10 server id 230  end_log_pos 118231 CRC32 0x0219bed2     Table_map: `business_db`.`SHOP_CASH_COUPON_USER_REF` mapped to number 178
# at 118231
#141125 17:41:10 server id 230  end_log_pos 118298 CRC32 0xc6665994     Write_rows: table id 178 flags: STMT_END_F
### INSERT INTO `business_db`.`SHOP_CASH_COUPON_USER_REF`
### SET
###   @1=4859
###   @2=284
###   @3=2425
###   @4=‘0‘
###   @5=‘2014-11-25 17:41:10‘
###   @6=NULL
# at 118298
#141125 17:41:10 server id 230  end_log_pos 118411 CRC32 0x93f6d105     Table_map: `business_db`.`CASH_TICKET` mapped to number 727
# at 118411
#141125 17:41:10 server id 230  end_log_pos 118703 CRC32 0xe4b314ad     Update_rows: table id 727 flags: STMT_END_F
### UPDATE `business_db`.`CASH_TICKET`
### WHERE
###   @1=19956
###   @2=1416886592
###   @3=NULL
###   @4=NULL
###   @5=1
###   @6=‘2014-12-31 00:00:00‘
###   @7=‘2014-11-25 00:00:00‘
###   @8=NULL
###   @9=NULL
###   @10=NULL
###   @11=NULL
###   @12=NULL
###   @13=NULL
###   @14=NULL
###   @15=NULL
###   @16=‘5c2483b3033b30c6b948d6a971c87f1d‘
###   @17=‘CASH-TICKET-1‘
###   @18=‘0‘
###   @19=000000050.000000000
###   @20=NULL
###   @21=284
###   @22=‘0‘
### SET
###   @1=19956
###   @2=1416908470
###   @3=‘PL.1qaz2wsx‘
###   @4=NULL
###   @5=1
###   @6=‘2014-12-31 00:00:00‘
###   @7=‘2014-11-25 00:00:00‘
###   @8=NULL
###   @9=2425
###   @10=‘PL.1qaz2wsx‘
###   @11=‘[email protected]‘
###   @12=‘4859‘
###   @13=NULL
###   @14=NULL
###   @15=NULL
###   @16=‘5c2483b3033b30c6b948d6a971c87f1d‘
###   @17=‘CASH-TICKET-1‘
###   @18=‘0‘
###   @19=000000050.000000000
###   @20=1416908470
###   @21=284
###   @22=‘0‘
# at 118703
#141125 17:41:10 server id 230  end_log_pos 118734 CRC32 0x6949012e     Xid = 16199116
COMMIT/*!*/;

看到这个执行成功的DML操作和一直RUNNING的事务时间上比较吻合,所以通过这binlog的INSERT语句和UPDATE语句,找到应用的一个业务模块的方法,发现其异常处理模块没有及时COMMIT和ROLLBACK的。 
    添加上ROLLBACK处理后,再测试N次,没有出现过报错信息,而执行SELECT * FROM `INNODB_TRX`;也没有记录,这表示事务都及时COMMIT或者ROLLBACK了。
5,期间遇到的额外问题 
Cause: java.sql.SQLException: Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED.; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException:   
--- The error occurred while applying a parameter map.  
--- Check the ITEM.updateByInventory-InlineParameterMap.  
--- Check the statement (update failed).  
--- Cause: java.sql.SQLException: Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED.
    处理方法:将BINLOG_FORMAT设置成MIXED即可,SET GLOBAL BINLOG_FORMAT = MIXED;

6,总结
    这个问题看似解决了,但是可能还有更多的细节没有梳理,为什么事务开启后没有ROLLBACK或者COMMIT,后续执行SELECT就会报错呢?自己想来是DML形成排它锁X,而查询是有共享锁S,X和S是互斥的(关于Innodb锁请参考:http://blog.itpub.net/26230597/viewspace-1315111/),所以就出问题了,至于源码层的底层分析,有待以后继续深究,如果有遇到此类问题的朋友,欢迎share下你的处理思路以及分析过程,谢谢。

----------------------------------------------------------------------------------------------------------------
<版权所有,文章允许转载,但必须以链接方式注明源地址,否则追究法律责任!>
原博客地址:  http://blog.itpub.net/26230597/viewspace-1346680/
原作者:黄杉 (mchdba)
----------------------------------------------------------------------------------------------------------------

时间: 2024-10-14 08:32:16

MySQL 事务RUNNING状态引发的Transaction timed out: deadline问题的相关文章

[原创]MySQL下关于begin或start transaction是否真正开启新事务的探索?

Server version:         5.6.21-log MySQL Community Server (GPL) 前提提要: 我们知道MySQL的RR(repeatable read)隔离级别下,事务无法看到正在活跃的事务所做的操作包括提交后的. 一般手动开启事务的命令是begin或start transaction:我以前的理解是一旦执行这条语句就已经开启了事务,也就是事务id已经生成(可用于MVCC版本比较),事务A和事务B一起执行begin,事务A的所有操作的提交事务B都看不

MySQL事务详解

事务:Transaction 多个sql语句,要么同时都执行,要么同时都不执行 事务就是一组原子性的(select)查询语句,也即将多个查询当作一个独立的工作单元 ACID测试:能够满足ACID测试就表示其支持事务,或兼容事务 A:Atomicity,原子性,都执行或者都不执行 C:Consistency,一致性,从一个一致性状态转到另外一个一致性状态 I:Isolaction,隔离性.一个事务的所有修改操作在提交前对其他事务是不可见的 D: Durability, 持久性,一旦事务得到提交,其

MYSQL事务及存储引擎对比

Innodb支持事务,而myisam不支持事务. 事务的定义: 当多个用户访问同一份数据时,一个用户在更改数据的过程中可能有其他用户同时发起更改请求,为保证数据的更新从一个一致性状态变更为另一个一致性状态,这时有必要引入事务的概念. Mysql提供了多种引擎支持Innodb和BDB.Innodb存储引擎事务主要通过UNDO日志和REDO日志实现,Myisam和memory引擎则不支持事务.下图分别给出三种mysql引擎的区别和特性: Myisam存储引擎:由于该引擎不支持事务.也不支持外键,所以

MySQL 事务功能

MySQL 事务功能 事务:  1.介绍 ★事务: 一组原子性的SQL查询.或者是一个或多个SQL语句组成的独立工作单元: ★ACID测试: ☉A:AUTOMICITY,原子性: 整个事务中的所有操作要么全部成功执行,要么全部失败后回滚: ☉C:CONSISTENCY,一致性: 数据库总是应该从一个一致性状态转为另一个一致性状态: ☉I:ISOLATION,隔离性: 一个事务所做出的操作在提交之前,是否能为其它事务可见:出于保证并发操作之目的,隔离有多种级别: ☉D:DURABILITY,持久性

Mysql事务-隔离级别

MYSQL事务-隔离级别 事务是什么? 事务简言之就是一组SQL执行要么全部成功,要么全部失败.MYSQL的事务在存储引擎层实现. 事务都有ACID特性: 原子性(Atomicity):一个事务必须被视为一个不可分割的单元: 一致性(Consistency):数据库总是从一种状态切换到另一种状态: 隔离性(Isolation):通常来说,事务在提交前对于其他事务不可见: 持久性(Durablity):一旦事务提交,所做修改永久保存数据库: 事务最常用的例子就是银行转账.假设polo需给lynn转

MySQL事务特性,隔离级别

事务特性ACID Atomic,原子:同一个事务里,要么都提交,要么都回滚: Consistency,一致性:即在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏: Isolation,隔离:并发事务间的行数据是彼此隔离的: Durability,持久:事务提交后,所有结果务必被持久化. MySQL支持事务的存储引擎:Innodb,NDBcluster,TokuD MySQL不支持事务的存储引擎:myisam  ,memory 1.隔离性通过锁的方式实现 2.原子性,一致性,持久性通过数

Mysql事务及行级锁

事务隔离级别 数据库事务隔离级别,只是针对一个事务能不能读取其它事务的中间结果. Read Uncommitted (读取未提交内容) 在该隔离级别,所有事务都可以看到其他未提交事务的执行结果.本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少.读取未提交的数据,也被称之为脏读( Dirty Read ). Read Committed (读取提交内容) 这是大多数数据库系统的默认隔离级别(但不是 MySQL 默认的).它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变.这

MySQL事务提交过程(二)

上一篇文章我们介绍了在关闭binlog的情况下,事务提交的大概流程.之所以关闭binlog,是因为开启binlog后事务提交流程会变成两阶段提交,这里的两阶段提交并不涉及分布式事务,当然mysql把它称之为内部xa事务(Distributed Transactions),与之对应的还有一个外部xa事务. 这里所谓的两阶段提交分别是prepare阶段和commit阶段. 内部xa事务主要是mysql内部为了保证binlog与redo log之间数据的一致性而存在的,这也是由其架构决定的(binlo

第五章 MySQL事务,视图,索引,备份和恢复

第五章 MySQL事务,视图,索引,备份和恢复 一.事务 1.什么是事务 事务是一种机制,一个操作序列,它包含了一组数据库操作命令,并且把所有的命令作为一个整体一起向系统提交或撤销操作请求.要么都执行,要么都不执行. 事务是作为最小的控制单元来使用的,特别使用与多用户同时操作的数据库系统. 2.为什么需要事务 事务(transaction)是指将一系列数据操作捆绑成为一个整体进行统一管理,如果某一事务执行成功,则在该事务中进行的所有数据均会提交,成为数据库中永久的组成部分.如果事务执行遇到错误且