MySQL 行锁优化

独占锁(X 锁)和共享锁(S 锁)是 InnoDB 的行级概念锁,用于确保对同一行记录的修改和删除的序列性,从而保证强一致性数据。它们适用于三种场景:记录锁、间隙锁和下一键锁。在高并发情况下,需要适当的配置以避免过多的死锁。

检查行锁等待情况

以下 SQL 语句可用于检查行锁等待情况。

show status like 'Innodb_row_lock_%';
返回参数说明
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_timeoutinteractive_timeout 参数,以设置等待获取资源的最大时长。这有助于优化锁机制,提高系统可用性。

在死锁不频繁发生的情况下,可以设置 innodb_print_all_deadlocks=ON 以在错误日志中打印每次死锁发生的详细信息,以帮助分析死锁的成因。然而,如果业务中死锁频繁,为了维护错误日志和服务器性能,最好将 innodb_print_all_deadlocks 设置为 OFF,仅输出死锁的汇总信息。如果需要详细的死锁分析,可以暂时将该参数设置为 ON,以观察一段时间内的详细死锁信息,然后再关闭以最小化对服务器性能的影响。

索引缺失

为了避免 InnoDB 由于无法通过索引获取行锁而升到表级锁,建议尽可能使用索引进行数据检索。此外,添加索引时应尽量精确,以避免不必要的锁定,这会影响其他查询的性能。

锁定范围过大

为了避免由于范围检索(即间隙锁)而锁定不应锁定的记录,建议最小化范围查询的使用。此外,为了减少被锁定的资源和锁定时间,应控制事务的大小。关于事务的隔离级别,建议在可行的情况下使用较低的隔离级别,以降低与 MySQL 事务隔离处理相关的成本。