首先需要确认锁的存在及具体原因,常用命令如下:
SHOW PROCESSLIST;,检查State列是否有“Waiting for table metadata lock”“Locked”等状态,或Info列是否有未提交的INSERT/UPDATE/DELETE语句。SHOW ENGINE INNODB STATUS\G,在输出中查找TRANSACTIONS部分,关注LOCK WAIT(等待锁的事务)和HOLDING LOCK(持有锁的事务)信息。INFORMATION_SCHEMA表获取更详细的锁信息,例如:SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS; -- 当前持有的锁
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS; -- 锁等待关系
-- MySQL 8.0+可使用performance_schema替代
SELECT * FROM performance_schema.data_locks; -- 当前锁信息
SELECT * FROM performance_schema.data_lock_waits; -- 锁等待信息
根据锁的类型和原因,采取针对性措施:
Time列值很大),可通过KILL <process_id>;命令终止该进程(process_id来自SHOW PROCESSLIST的输出)。注意:终止事务可能导致部分数据未提交,需谨慎操作。WHERE子句中的字段有索引,避免全表扫描(如UPDATE table SET col=value WHERE id=1中,id应为索引字段)。REPEATABLE READ(默认)降低到READ COMMITTED,减少锁冲突(如SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;)。但需注意:READ COMMITTED可能出现不可重复读。version字段,更新时检查版本号:UPDATE table SET col=value, version=version+1 WHERE id=1 AND version=old_version),避免表锁。SHOW PROCESSLIST或查询INFORMATION_SCHEMA表,设置告警(如通过脚本监控innodb_lock_wait_timeout触发的锁等待事件)。innodb_lock_wait_timeout(默认50秒),避免长时间等待(如SET GLOBAL innodb_lock_wait_timeout=30;)。InnoDB会自动检测死锁(默认开启),并回滚其中一个事务(称为“死锁牺牲者”)。可通过以下方式处理:
innodb_print_all_deadlocks=ON(默认关闭),死锁信息会写入MySQL错误日志(路径:/var/log/mysql/error.log),可通过SHOW VARIABLES LIKE 'innodb_print_all_deadlocks';开启。1213),在应用中实现重试逻辑(如等待1秒后重新执行事务)。