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

本文详细解析了TransactionTimedout异常的原因,通过检查Innodb状态和表锁,发现事务未正常提交或回滚导致的问题。通过分析慢查询日志和binlog,定位到业务模块中未处理的异常,最终通过添加ROLLBACK处理解决了问题。


前言:
    朋友说简单的查询导致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='1qaz2wsx@163.com'
###   @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锁请参考之前的博客),所以就出问题了,至于源码层的底层分析,有待以后继续深究,如果有遇到此类问题的朋友,欢迎share下你的处理思路以及分析过程,谢谢。
 

<think>好的,我现在遇到了一个Spring框架的异常:org.springframework.transaction.TransactionTimedOutException,提示事务超时,截止时间是2025年8月19日17:20:29 JST。用户想知道怎么解决这个问题。首先,我需要回忆一下Spring事务管理的相关知识。 首先,这个异常通常发生在事务执行时间超过了配置的超时时间。可能的原因有很多,比如数据库操作耗时太长,或者事务中包含了不必要的操作,导致执行时间过长。也有可能是数据库连接池的问题,或者数据库本身的性能问题。 接下来,我应该考虑如何定位问题。首先检查事务的配置,看看是否设置了合适的超时时间。默认情况下,Spring的事务超时可能没有设置,或者设置得比较短。可以通过在@Transactional注解中设置timeout属性,或者在配置文件中调整超时时间。但仅仅增加超时时间可能不是最好的解决方案,因为这可能掩盖了更深层次的问题。 然后,需要分析事务中的具体操作。是否存在复杂的查询或者大量的数据处理?是否有可以优化的地方,比如添加索引、减少查询次数、使用分页等。此外,检查是否有锁竞争的情况,比如长时间的行锁或表锁导致其他事务等待。 另外,检查数据库连接池的配置也很重要。如果连接池中的连接数不足,可能会导致事务等待连接,从而超时。调整连接池的大小,或者优化连接的使用情况,比如及时释放资源,可能有助于解决问题。 还可能存在代码层面的问题,比如事务边界设置不当,导致事务包含过多的操作。应该尽量保持事务的简洁,只在需要的时候开启事务,并在完成后及时提交或回滚。此外,检查是否有循环依赖或者重复提交事务的情况。 还需要考虑应用服务器或数据库服务器的性能问题,比如CPU、内存、磁盘I/O是否达到瓶颈。监控系统资源,找出可能的瓶颈并进行优化。 最后,日志和监控工具可以帮助更详细地分析问题。通过查看事务执行的具体耗时,确定哪个部分耗时最长,从而有针对性地优化。 总结来说,解决这个问题需要多方面的检查和调整,包括事务配置、代码优化、数据库性能调优以及系统资源监控。需要逐步排查可能的原因,找到根本问题所在,而不是仅仅延长超时时间。</think>出现 TransactionTimedOutException 异常表示事务执行时间超过了配置的超时限制,以下是具体解决方案: 1. **检查事务配置** ```java @Transactional(timeout = 30) // 显式设置超时时间(单位:秒) ``` - 调整 `timeout` 参数值(默认为-1表示无超时) - 在 XML 配置中检查 `<tx:advice>` 的 `timeout` 设置 2. **优化事务内操作** ```sql -- 示例:为慢查询添加索引 CREATE INDEX idx_user_name ON users(name); ``` - 拆分复杂事务为多个小事务 - 避免在事务中进行大量数据处理 - 使用分页查询替代全表扫描 3. **检查数据库连接池配置** ```yaml spring: datasource: hikari: maximum-pool-size: 10 connection-timeout: 30000 ``` - 确保连接池大小与并发需求匹配 - 监控连接池使用情况(如 HikariCP 提供的 metrics) 4. **排查死锁/锁竞争** ```sql -- MySQL 死锁检测语句 SHOW ENGINE INNODB STATUS; ``` - 使用数据库工具分析锁等待 - 避免在事务中对相同资源的交叉访问 5. **启用事务监控** ```properties # 启用 Spring 事务统计日志 spring.jpa.properties.hibernate.generate_statistics=true ``` - 使用 APM 工具(如 SkyWalking)追踪事务耗时 - 分析事务各阶段耗时分布
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值