一個管理後臺的管理員提出一個修改功能異常的問題,追蹤發現數據修改出現了異常
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
; SQL []; Lock wait timeout exceeded; try restarting transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:259)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:71)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:365)
at com.sun.proxy.$Proxy19.update(Unknown Source)
............
初步判斷是出現了鎖等待,去數據庫查看,發現對應的那一條記錄大部分字段是可以更改的!只有一個關鍵的字段不能更改!
這個時候還不太瞭解mysql的各種鎖,使用 SHOW PROCESSLIST 和 SHOW ENGINE INNODB STATUS 也並沒有找到問題
通過查找資料,找到了解決辦法 SELECT * FROM information_schema.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`
'1231918001','RUNNING','2017-09-12 20:05:17',NULL,NULL,'10','637994104',NULL,NULL,'0','0','7','1184','17','3','0','READ COMMITTED','1','1',NULL,'0','10000','0','0');
一條很奇怪的記錄。沒有sql語句。通過trx_mysql_thread_id 去SHOW PROCESSLIST中找到對應的記錄,發現這個線程是sleep狀態
kill掉之後,回覆正常。
查找分析,個人認爲是因爲gap鎖導致的死鎖問題,恰好本次涉及到的問題字段是索引字段。
下面這篇文章對本次問題已經MySQL的理解有很大的幫助
https://tech.meituan.com/innodb-lock.html