1 、故障描述
某次某用户的
MySQL
集群
mgr
主节点产生大量
running
连接且长时间无法执行完成,详细信息如下所示:

2 、根因分析
根据提示,初步判断是有大量事务未提交,导致锁无法释放。但这两个截图无法确定是哪个事务占用了锁导致,需要进一步排查。
尝试先将问题线程 kill 掉,再做跟踪观察,如下:

select * from information_schema.processlist where command !='Sleep';
确实可以发现,此时出现了很多的 MDL 锁等待情况,正常情况下,执行 create database 不会有 MDL 锁存在,从语句上来看,是去判断库是否存在,不存在就创建。而这些库其实是存在的,业务上一直在做判断执行。
那么很有可能是当前库下有 DML 操作,执行该 DDL 操作,会等待所有 DML 操作完成才能执行,而 DDL 之后又执行的 DML 又需要等待该 DDL 完成,从而导致了恶心循环,一般这种情况再 rr 隔离级别容易出现。此时去查看当前实例的隔离级别,发现确实是 RR ,如下:
mysql> show variables like 'transaction_isolation';
+-----------------------+----------------+
| Variable_name | Value |
+-----------------------+----------------+
| transaction_isolation | READ- REPEATABLE |
+-----------------------+----------------+
1 row in set (0.00 sec)
当然,排查过程中还发现了 BUFFER 缓冲内存配置较低,在高频查询场景中可能会出现严重的性能问题,如下:
show variables like 'innodb_buffer_pool_size' ;
+-------------------------+-----------+
| Variable_name | Value |
+-------------------------+-----------+
| innodb_buffer_pool_size | 134217728 |
+-------------------------+-----------+
内存设置太小, MySQL 根本无法进行缓存以及上下文切换。可根据实际情况将内存扩大至服务器内存的 60% 。
3 、解决方案
1 、在线将 MySQL 事务隔离级别改为 RC
set global transaction isolation level read committed;
添加到配置文件 my.cnf
transaction-isolation=READ-COMMITTED
Kill 掉全部有锁的 SQL 或者重启实例 , 观察新 session ,恢复正常
2 、将 buffer 手动扩容至 10GB
set global innodb_buffer_pool_size = 10*1024*2014*1024
