排他锁(X 锁)和共享锁(S 锁)是 InnoDB 的行级概念锁,用于保证对同一行记录的修改和删除的串行性,从而确保强数据一致性。它们应用于三种场景:记录锁、间隙锁和临键锁。在高并发情况下,需要合理配置以避免过多的死锁。
可以使用以下 SQL 语句检查行锁等待情况。
| 返回参数 | 说明 |
|---|---|
| Innodb_row_lock_current_waits | 当前行锁等待的数量 |
| Innodb_row_lock_time | 获取行锁总耗时,单位为毫秒 |
| Innodb_row_lock_time_avg | 获取行锁平均耗时,单位为毫秒 |
| Innodb_row_lock_time_max | 获取行锁最大耗时,单位为毫秒 |
| Innodb_row_lock_waits | 行锁等待发生的次数 |
当 MySQL 遇到过多并发请求时,会因争抢行锁而产生等待。为避免锁冲突,建议优化业务中的热点更新,并在处理大量数据时采用分页查询或分段查询等方式,避免单次查询锁定过多数据行,从而降低锁冲突风险,提高系统性能和响应速度。此外,可调整 innodb_lock_wait_timeout 和 interactive_timeout 参数,设置事务等待获取资源的最大时长,优化锁机制,提升系统可用性。
当死锁较少时,可设置 innodb_print_all_deadlocks=ON,将每次死锁的详细信息打印到错误日志,辅助分析死锁原因。但如果业务中死锁较为频繁,为了维护错误日志和服务器性能,建议将 innodb_print_all_deadlocks 设置为 OFF,仅输出死锁的概要信息。如需详细死锁分析,可临时将该参数设为 ON,观察一段时间的死锁详细信息后再关闭,以尽量减少对服务器性能的影响。
为避免 InnoDB 因无法通过索引获取行锁而升级为表锁,建议尽可能使用索引进行数据检索。同时,添加索引时应尽量精准,避免不必要的锁定,影响其他查询的性能。
为避免因范围检索(即间隙锁)而锁定不应锁定的记录,建议尽量减少范围查询的使用。此外,为减少锁定资源量和锁定时间,应控制事务大小。关于事务隔离级别,建议在可行的情况下使用较低的隔离级别,以降低 MySQL 事务隔离处理的成本。