这是学习笔记的第 1911 篇文章
今天晚上的时候,突然发现我们的运维系统不可访问了,最开始以为是网络的问题,查看后端没有报错,依然有业务输出日志。怀疑是网络的访问导致,重启了应用服务,依然访问失败,接着查看数据库端,让人担心的事情还是发生了,数据库里面有大量的线程,还是大多数都处于阻塞状态。
这是一套基于MGR的多主环境,目前存在两个节点,都是可写的。初步分析这个问题,是由于事务的阻塞导致的,而且应该属于连锁反应。
那么看起来只要kill掉阻塞线程即可,但是查看已有的线程都是清一色的commit,所以为了尽快恢复业务,我们选择先kill掉这些线程,先选择kill了一小部分,没想到马上得到了应用的回复,连接数直线上升,原来还是400多个,现在成了600多个,马上数据库就无法连接了,应用端完全阻塞,而另外一个节点却没有丝毫的变化,线程数都正常。
情况类似下图所示:
显然问题升级了,这个时候查看当前的锁情况,通过sys schema得到了一些线索。
>select *from innodb_lock_waits \G
*************************** 1. row ***************************
wait_started: 2019-03-07 20:12:22
wait_age: 00:00:20
wait_age_secs: 20
locked_table: `devopsdb`.`xxxx_backup_rs`
locked_index: PRIMARY
locked_type: RECORD
waiting_trx_id: 2295941
waiting_trx_started: 2019-03-07 20:12:22
waiting_trx_age: 00:00:20
waiting_trx_rows_locked: 1
waiting_trx_rows_modified: 0
waiting_pid: 113071
waiting_query: insert into `xxxx_backup_ ... name`=values(`physeevicename`)
waiting_lock_id: 2295941:587:59498:85
waiting_lock_mode: X
blocking_trx_id: 2295230
blocking_pid: 111437
blocking_query: commit
blocking_lock_id: 2295230:587:59498:85
blocking_lock_mode: X
blocking_trx_started: 2019-03-07 19:06:29
blocking_trx_age: 01:06:13
blocking_trx_rows_locked: 3
blocking_trx_rows_modified: 3
sql_kill_blocking_query: KILL QUERY 111437
sql_kill_blocking_connection: KILL 111437
1 row in set, 3 warnings (0.01 sec)
可以看到是在2019-03-07 19:06:29的一个事务,相关SQL是insert语句,在commit的时候突然阻塞了,这个阻塞导致了后续的操作都产生了堆积。
那么111437是哪个线程呢,我们简单定位发现是另外一个服务器发起的数据请求。
| 111437 | dev_trans_rwl | xxxx:63077 | devopsdb | Query | 2837 | starting | commit
简单来看insert是无辜的,因为它的逻辑很简单,但是一定是碰到了其他的因素,而经过一番排查发下,这个原因就是delete,这个操作的瓶颈就在于delete语句,其中表数据有500万,但是delete的逻辑是没有指定索引,也就意味着是全表扫描了,所以这种情况下在事务中是很可能导致阻塞的。
kill了线程之后也没有奏效,那些线程都标识为KILLED的,但是没有释放。
这种情况下,flush相关的操作也会hang住,所以果断对当前数据库做重启恢复。
整个过程持续了几分钟,最后数据库启动后,发现一个奇怪的问题,那就是IDC2-MGR 的节点也退出了集群。也就意味着没有了高可用保护。
最后我们重新在IDC1-MGR启动集群然后加入IDC2-MGR节点。
对于这个问题我们通过日志的初步分析是IDC1-MGR节点存在大事无阻塞,没有提交导致数据变更没有同步到IDC2-MGR,这样超过一定阈值之后,IDC1-MGR节点停止推出集群后,IDC2-MGR为了保证集群的稳定,也停止了GR复制,听起来好像不是很顺。主要还是基于数据的完整性保护,我们后续做了测试,对运行平稳,写入正常的环境重启IDC2-MGR,多主环境是正常的,可以提供持续性访问。
对于2个MGR节点如此,其实从分布式的角度来说,对于3个节点也是类似的。如下图所示:
如果数据变更的压力都是IDC1-MGR,如果数据变化都难以同步到IDC2-MGR,IDC3-MGR,那么这个过程中从分布式协议的算法来说,这是属于异常情况,而为了保持集群的稳定,是需要剔除IDC1-MGR的。
相关链接: