Mysql造成鎖的情況有很多,以下列了4種情況:
- 執行DML操作沒有commit,再執行刪除操作就會鎖表;
- 在同一事務內先后對同一條數據進行插入和更新操作;
- 表索引設計不當,導致數據庫出現死鎖;
- 長事物,阻塞DDL,繼而阻塞所有同表的后續操作。
出現事務鎖表等待,解決的辦法有四種:
(1)找出出現鎖表的事務進程殺死;
(2)進行sql語句分析,優化慢sql;
(3)把事務等待時間延長;
(4)修改表的存儲引擎為innodb。
一、找出出現鎖表的事務進程,然后將其殺死
# 查看數據庫當前正在執行的進程,只是顯示部分
show processlist;
# 顯示所有的正在進行的進程
show full processlist;
# 當前運行的所有事務
SELECT * FROM information_schema.INNODB_TRX;
# 當前出現的鎖
SELECT * FROM information_schema.INNODB_LOCKs;
# 鎖等待的對應關系
SELECT * FROM information_schema.INNODB_LOCK_waits;
#解釋:看事務表INNODB_TRX,里面是否有正在鎖定的事務線程,
看看ID是否在show processlist里面的sleep線程中,
如果是,就證明這個sleep的線程事務一直沒有commit或者rollback而是卡住了。
trx_mysql_thread_id 即為事務線程id。
我們需要使用kill id 命令將其殺死。
二、進行sql語句分析,優化慢sql
找到出現問題源代碼位置,然后分析一下是否存在慢sql,然后對其進行優化。最好還是檢查一下事務的使用是否使用正確,如果事務使用不正確也會導致這樣的問題。
三、延長事務超時等待時間
# 將事務超時等待的時間設置長一點 執行以下兩條sql
SET GLOBAL innodb_lock_wait_timeout = 5000;
SET innodb_lock_wait_timeout = 5000;
四、查看和修改表的存儲引擎
# 查看當前數據庫所支持的引擎 (mysql5.5.5以前默認是MyISAM,mysql5.5.5以后默認是InnoDB)
show ENGINES;
# 查看當前數據庫的版本
SELECT VERSION();
# 查看表使用的存儲引擎
show table status from db_name where name='table_name';
# 修改表的存儲引擎
alter table table_name engine=innodb;
參考鏈接:
(1) https://www.jianshu.com/p/0b4aaa93e7f6 (事務鎖表分析以及解決方案)
(2) https://stackoverflow.com/questions/2766785/fixing-lock-wait-timeout-exceeded-try-restarting-transaction-for-a-stuck-my/10315184 (Stack Overflow 事務鎖表解決方案)
(3)https://zhuanlan.zhihu.com/p/30743094 (show processlist 詳解)
(4)https://dev.mysql.com/doc/refman/5.6/en/general-thread-states.html (mysql官網 States 的狀態解析描述)
(5) https://ningyu1.github.io/site/post/75-mysql-lock-wait-timeout-exceeded/ (事務問題分析以及解決方案)