MySQL锁等待导致连接数被打满处理分析
内容提要
讨论MySQL中的行锁等待问题,导致数据库连接数和CPU占用率飙升。通过查看系统表和执行SQL语句,可以查看正在执行的事务、正在锁的事务和等待锁的事务。解决锁等待问题的方法包括使用合适的事务隔离级别、减少事务长度、避免频繁更新同一行数据、约定不同事务以相同顺序访问多行记录、及时提交或回滚事务、为表添加合适的索引等。
延伸解读
锁等待为何会打满连接数
文章指出,行锁等待本身是正常现象,但若持有锁的会话因客户端中断等原因长时间不释放,其他会话就会持续等待。业务端以10Hz频率重试update,导致等待线程迅速堆积,连接数从100多飙升至400多,CPU从4%升至100%,最终连接数被打满。这说明锁等待的破坏力不仅在于锁本身,更在于应用层的重试策略会放大故障。
排查锁等待的实用路径
文章给出了明确的排查顺序:先查information_schema.innodb_trx找到处于LOCK WAIT状态的事务,再结合innodb_locks和innodb_lock_waits定位阻塞源,也可直接使用sys.innodb_lock_waits视图获取杀链接SQL。通过trx_mysql_thread_id可关联到具体线程,必要时用KILL命令终止等待事务。这套方法能快速定位问题,但需注意在5.7版本中这些系统表才可用。
预防锁等待的六个设计要点
文章建议从六个方面降低锁竞争:选择READ COMMITTED或REPEATABLE READ隔离级别、尽量缩短事务长度、避免频繁更新同一行、多行访问时约定相同顺序、及时提交或回滚事务、为表添加合适索引。这些措施的核心是减少锁的持有时间和冲突概率,尤其适合高并发更新场景。但文章未给出具体参数调优建议,实际落地时需结合业务特点权衡。
Q&A
MySQL行锁等待导致连接数飙升的原因是什么?
业务update语句存在行锁等待,短时间内大量重试(频率10Hz)导致实例CPU打满,随后最大连接数打满。
如何查看MySQL中正在等待锁的事务?
可以查询information_schema.innodb_trx表,筛选trx_state='LOCK WAIT'的事务;也可以查询information_schema.innodb_lock_waits表查看锁等待关系;还可以使用sys.innodb_lock_waits视图。
处理MySQL锁等待的步骤有哪些?
1. 查询innodb_trx表找到处于LOCK WAIT状态的事务;2. 结合innodb_locks和innodb_lock_waits表定位阻塞事务;3. 通过SHOW ENGINE INNODB STATUS查看死锁信息;4. 使用SHOW FULL PROCESSLIST找到线程ID;5. KILL掉发生锁等待的线程。
如何避免MySQL行锁等待?
使用合适的事务隔离级别(如READ COMMITTED或REPEATABLE READ);尽量减少事务长度;避免频繁更新同一行数据;约定不同事务以相同顺序访问多行记录;及时提交或回滚事务;为表添加合适的索引。
InnoDB如何处理死锁?
InnoDB有内部机制检测死锁,并通常会终止其中一个事务,以便让另一个事务继续执行。
information_schema.innodb_locks表有哪些关键字段?
关键字段包括:lock_id(锁ID)、lock_trx_id(拥有锁的事务ID)、lock_mode(锁模式,如S、X、IS、IX等)、lock_type(锁类型,RECORD或TABLE)、lock_table(被锁定的表名)、lock_index(索引名)、lock_data(锁定行的主键)等。