在MySQL主從架構集群中,如果主庫發生故障,需要立刻提升一個從庫為新主庫。在這個過程中,有一個操作是在從庫上執行stop slave
停止復制的操作,一般情況下,會非常順利。
但也有特殊情況下,會遇到stop slave
被卡住的問題。
這樣,給故障恢復過程造成了一定的困擾。
本文模擬一種stop slave
被卡住的情況。
MySQL版本: 5.7.27-log
1.模擬過程
首先准備一個主從集群,具體過程參見MySQL主從集群搭建。
1.1.主庫數據准備
mysql> create database app;
Query OK, 1 row affected (0.01 sec)
mysql>
CREATE TABLE `test` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`service_group_name` varchar(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
1.2 從庫加讀鎖
首先保證從庫復制正常,start slave
已開啟復制。
在從庫上打開終端1,對數據表test
加讀鎖:
mysql> lock tables app.test read;
Query OK, 0 rows affected (0.00 sec)
mysql>
1.3 主庫寫入數據
在主庫上寫入一條數據:
mysql> insert into test(service_group_name) values('abc');
Query OK, 1 row affected (0.01 sec)
這個步驟是必須的,否則無法復現卡住問題。
1.4 從庫 stop slave
在從庫上,打開另一個終端2,執行stop slave
,被卡住:
mysql> stop slave;
而且,
從庫終端1上,執行解鎖操作unlock tables;
。
從庫終端2上被卡住的命令會立刻返回。
2.原因
在從庫上執行show processlist
:
mysql> show processlist;
+----+-------------+-----------+------+---------+------+----------------------------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-------------+-----------+------+---------+------+----------------------------------+------------------+
| 2 | root | localhost | app | Query | 0 | starting | show processlist |
| 15 | root | localhost | NULL | Query | 66 | Killing slave | stop slave |
| 27 | system user | | NULL | Connect | 2589 | Waiting for master to send event | NULL |
| 28 | system user | | NULL | Connect | 73 | Waiting for table metadata lock | NULL |
+----+-------------+-----------+------+---------+------+----------------------------------+------------------+
4 rows in set (0.00 sec)
stop slave
一直處於Killing slave
狀態。
前面已經提到,在從庫上加鎖后,必須在主庫上寫入數據,問題才會復現,因此推測,
問題原因可能是,read lock
與 SQL thread
死鎖造成的。
3.其他被卡住的情況
在網上搜到一種情況是,
執行flushs tables with read lock
以及show slave status
會有可能和SQL Thread形成死鎖,導致SQL Thread一直被卡住。這樣,stop slave
就被卡住了。
這種情況跟 #70307 bug 有關。