- GreatSQL社區原創內容未經授權不得隨意使用,轉載請聯系小編并注明來源,
- GreatSQL是MySQL的國產分支版本,使用上與MySQL一致,
- 作者: 王權富貴
- 文章來源:GreatSQL社區原創
背景
在一次日常測驗中發現,kill 一個會話后,SQL陳述句依然在運行并沒終止;被kill的會話重新連接并繼續執行原來的SQL陳述句,
測驗
本次測驗基于MySQL 8.0.27
1.創建測驗表
create table t1 (id int, name varchar(30));
insert into t1 values (1,'a'),(2,'b');
2.開啟3個會話
| session1 | session2 | session3 |
|---|---|---|
| begin; | ||
| select * from t1; | ||
| rename table t1 to t2; 【由于鎖等待,hang住】 | ||
| show processlist; 【查看 processlist_id】 | ||
| kill session2; | ||
| 【session2 重新連接并且繼續執行陳述句,處于鎖等待狀態】 | ||
| show processlist; 【可以看到session2重新連接并繼續執行SQL】 | ||
| commit; | ||
| 【rename 執行成功】 | ||
| show tables; 【t1 被 rename 為 t2】 |
session1:開啟一個事務不提交
mysql> use test
Database changed
mysql>
mysql>
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from t1;
+------+------+
| id | name |
+------+------+
| 1 | a |
| 2 | b |
+------+------+
2 rows in set (0.00 sec)

session2:執行DDL陳述句
mysql> use test
Database changed
mysql>
mysql>
mysql> rename table t1 to t2;

session3:kill session2
mysql> show processlist;
+-----+------+---------+---------+--------------------------------+----------------------+
| Id | db | Command | Time | State | Info |
+-----+------+---------+---------+--------------------------------+----------------------+
| 6 | NULL | Daemon | 4399013 | Waiting on empty queue | NULL |
| 132 | test | Sleep | 232 | | NULL |
| 134 | test | Query | 123 | Waiting for table metadata lock| rename table t1 to t2|
| 135 | test | Query | 0 | init | show processlist |
+-----+------+---------+---------+--------------------------------+----------------------+
4 rows in set (0.00 sec)
mysql> kill 134;
Query OK, 0 rows affected (0.01 sec)
#為了排版,表格欄位略有刪減,具體資訊請看圖片

session2:session2重新連接,并且繼續執行DDL陳述句,仍處于鎖等待狀態
mysql> rename table t1 to t2;
ERROR 2013 (HY000): Lost connection to MySQL server during query
No connection. Trying to reconnect...
Connection id: 136
Current database: test

session3:查看會話資訊
mysql> show processlist;
+-----+------+---------+---------+--------------------------------+----------------------+
| Id | db | Command | Time | State | Info |
+-----+------+---------+---------+--------------------------------+----------------------+
| 6 | NULL | Daemon | 4399260 | Waiting on empty queue | NULL |
| 132 | test | Sleep | 479 | | NULL |
| 135 | test | Query | 0 | init | show processlist |
| 136 | test | Query | 193 | Waiting for table metadata lock| rename table t1 to t2|
+-----+------+---------+---------+--------------------------------+----------------------+
4 rows in set (0.00 sec)
#為了排版,表格欄位略有刪減,具體資訊請看圖片

可以看到, kill session2 后,session2 重新連接并且繼續執行SQL
session1:提交事務
mysql> commit;
Query OK, 0 rows affected (0.01 sec)

session2:執行成功
mysql> use test
Database changed
mysql>
mysql>
mysql> rename table t1 to t2;
ERROR 2013 (HY000): Lost connection to MySQL server during query
No connection. Trying to reconnect...
Connection id: 136
Current database: test
Query OK, 0 rows affected (8 min 38.00 sec)

通過上述測驗,可以看到明明執行了 kill 命令,但是依然沒有達到我們想要的效果,似乎 kill 命令沒有生效一樣,
經過查詢資料發現,由于通過MySQL客戶端登錄,--reconnect 重新連接選項默認是開啟的,該選項在每次連接丟失時都會進行一次重新連接嘗試;因此在kill session2 后,session2重新連接并再次執行之前的SQL陳述句,導致感覺 kill 命令沒有生效,
--reconnect Reconnect if the connection is lost. Disable with
--disable-reconnect. This option is enabled by default.
(Defaults to on; use --skip-reconnect to disable.)
解決
可以通過以下2種方式避免上述問題的發生:
1.執行kill query 命令
KILL QUERY終止連接當前正在執行的陳述句,但保持連接本身不變
session3:執行 KILL QUERY 命令
mysql> show processlist;
+-----+------+---------+---------+--------------------------------+----------------------+
| Id | db | Command | Time | State | Info |
+-----+------+---------+---------+--------------------------------+----------------------+
| 6 | NULL | Daemon | 4401560 | Waiting on empty queue | NULL |
| 132 | test | Sleep | 11 | | NULL |
| 135 | test | Query | 0 | init | show processlist |
| 137 | test | Query | 3 | Waiting for table metadata lock| rename table t1 to t2|
+-----+------+---------+---------+--------------------------------+----------------------+
4 rows in set (0.00 sec)
mysql>
mysql> kill query 137;
Query OK, 0 rows affected (0.00 sec)
#為了排版,表格欄位略有刪減,具體資訊請看圖片

session2:
mysql> rename table t1 to t2;
ERROR 1317 (70100): Query execution was interrupted

可以看到session2執行的陳述句已經被終止了,達到了我們想要的效果,
2.登錄mysql客戶端時加--skip-reconnect選項
--skip-reconnect 表示當連接丟失時不會進行重新連接的嘗試
session2:登錄時加 --skip-reconnect 選項
shell> mysql -uroot -p -h127.0.0.1 -P3306 --skip-reconnect
session3:執行 kill 命令
mysql> show processlist;
+-----+------+---------+---------+--------------------------------+----------------------+
| Id | db | Command | Time | State | Info |
+-----+------+---------+---------+--------------------------------+----------------------+
| 6 | NULL | Daemon | 4402073 | Waiting on empty queue | NULL |
| 132 | test | Sleep | 524 | | NULL |
| 135 | test | Query | 0 | init | show processlist |
| 139 | test | Query | 4 | Waiting for table metadata lock| rename table t1 to t2|
+-----+------+---------+---------+--------------------------------+----------------------+
4 rows in set (0.00 sec)
mysql> kill 139;
Query OK, 0 rows affected (0.00 sec)

session2:
mysql> rename table t1 to t2;
ERROR 2013 (HY000): Lost connection to MySQL server during query

可以看到session2的會話連接已經被終止,并且沒有自動重新連接,達到了我們想要的效果,
總結
-
通過MySQL客戶端登錄時,會話重新連接的選項
--reconnect默認是開啟的,如果要禁止重新連接可在登錄時添加 --skip-reconnect -
KILL CONNECTION與KILL相同,它在終止連接正在執行的任何陳述句后,再終止會話連接, -
KILL QUERY終止連接當前正在執行的陳述句,但保持連接本身不變,
參考鏈接
https://dev.mysql.com/doc/refman/8.0/en/kill.html
https://dev.mysql.com/doc/refman/8.0/en/mysql-command-options.html
Enjoy GreatSQL ??
關于 GreatSQL
GreatSQL是由萬里資料庫維護的MySQL分支,專注于提升MGR可靠性及性能,支持InnoDB并行查詢特性,是適用于金融級應用的MySQL分支版本,
相關鏈接: GreatSQL社區 Gitee GitHub Bilibili
GreatSQL社區:
社區博客有獎征稿詳情:https://greatsql.cn/thread-100-1-1.html

技術交流群:
微信:掃碼添加
GreatSQL社區助手微信好友,發送驗證資訊加群,

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/547988.html
標籤:其他
上一篇:初識Kafka
