首先需要确认锁的存在及具体原因,常用命令如下:
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秒后重新执行事务)。