對wait_timeout引發的問題的分析及解決辦法


美好的清晨遇到一到讓人增長知識的錯誤!

1、錯誤現象

MySQL連接錯誤,具體報錯信息如下:

The last packet sent successfully to the server was 47,795,922 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.

所使用的MySQL的版本爲:

mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.15    |
+-----------+

2、發生場景

錯誤發生的場景是這樣的, 使用MySQL8作爲kettle的資源庫,在經過一夜沒有操作kettle後,第二天一大早使用kettle打開之前建好的作業時,報了上面的錯誤。
所報的錯誤信息是,上次成功發往MySQL服務的數據包發生在47795922毫秒之前,而該時間值超過了MySQL服務所配置的wait_timeout的時長。

3、解決思路

自然而然想到的解決辦法就是增加wait_timeout的時間,wait_timeout參數有兩種作用範圍:session和global,鑑於在交互式方式下修改這兩種範圍下wait_timeout在重啓MySQL server後都會失效,這裏再介紹一種修改MySQL配置文件(my.conf)的方式,所以下面共提供了三種修改wait_timeout值的方式。

4、具體解決方式

以下操作在CentOS7.5下進行。

4.1、方式一:設置session範圍的wait_timeout

登錄進MySQL server,使用下面命令查看當前session的wait_timeout值:

mysql> show session variables like "wait_timeout";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 28800 |
+---------------+-------+
1 row in set (0.01 sec)

可以看到wait_timeout的值默認爲28800,單位爲s(秒),換算成小時爲小時,如果不在上面的命令中添加session,默認查詢的也是當前session範圍內的wait_timeout值。
使用下面的命令設置當前session的wait_timeout值,如果不加session,默認值設置的也是當前session範圍內的wait_timeout值,並再次查看其值:

mysql> show session variables like "wait_timeout";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 100   |
+---------------+-------+
1 row in set (0.00 sec)

mysql> set session wait_timeout=100;
Query OK, 0 rows affected (0.00 sec)

mysql> show session variables like "wait_timeout";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 100   |
+---------------+-------+
1 row in set (0.00 sec)

設置當前session範圍內的wait_timeout值,當退出當前session時所設置的值會丟失,再次登錄MySQL server會發現wait_timeout值已變成默認值——28800 ,要想退出session而不丟失更改,可以考慮設置global範圍的wait_timeout值,即下面的方式二。

4.2、方式二:設置global範圍的wait_timeout

登錄進MySQL server,使用下面命令查看global範圍的wait_timeout值

mysql> show global variables like "wait_timeout";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 28800 |
+---------------+-------+
1 row in set (0.00 sec)

使用下面的命令設置global的wait_timeout值,並再次查看其值:

mysql> set global wait_timeout=300;
Query OK, 0 rows affected (0.00 sec)

mysql> show global variables like "wait_timeout";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 300   |
+---------------+-------+
1 row in set (0.00 sec)

4.2.1、思考

介紹到這裏有一個問題值得思考,在設置了global範圍的wait_timeout後,session範圍的wait_timeout值是否會發生變化呢?
經過查看發現session範圍的wait_timeout值並沒有隨着global範圍的wait_timeout值的改變而改變。其實在MySQL官網的參考手冊上對wait_timeout的有這樣一段解釋:

The number of seconds the server waits for activity on a noninteractive connection before closing it.

On thread startup, the session wait_timeout value is initialized from the global wait_timeout value or from the global interactive_timeout value, depending on the type of client (as defined by the CLIENT_INTERACTIVE connect option to mysql_real_connect()). See also interactive_timeout.

wait_timeout指的是,在非交互連接方式下,MySQL server等到一個活動的時間,如果超出這個時間仍沒有等到連接活動,MySQL server就會斷開連接。在連接啓動時,session範圍的wait_timeout的值是根據客戶端類型來確定的,要麼初始化於global wait_timeout要麼初始化於global interactive_timeout。那什麼是interactive_timeout呢,在MySQL官網的參考手冊上同樣也有對它的解釋:

The number of seconds the server waits for activity on an interactive connection before closing it. An interactive client is defined as a client that uses the CLIENT_INTERACTIVE option to mysql_real_connect(). See also wait_timeout.

interactive_timeout指的是,在交互式連接方式下,MySQL server等待一個活動的時間,如果超出這個時間仍沒有等到連接活動,MySQL server就會斷開連接。
瞭解了session範圍的wait_timeout值的來源,就能根據需要設定它的值了。在交互式連接中,我們先設置global範圍的interactive_timeout值,然後重新建立連接,再次查詢session範圍的wait_timeout值是否發生改變,驗證過程如下:

mysql> set global interactive_timeout=300;
Query OK, 0 rows affected (0.00 sec)

mysql> exit
Bye
[xiaoliu@laptop-8a061sac ~]$ mysql -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.15 MySQL Community Server - GPL

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show variables like "wait_timeout";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 300   |
+---------------+-------+
1 row in set (0.01 sec)

可以看出,在交互模式下,session範圍內的wait_timeout值已變爲設置的global範圍的interactive_timeout的值。
設置了global範圍的wait_timeout之後,當服務器重啓或者MySQL server重啓後,上面的方式設置的值都會丟失,如何才能不丟失呢,需要把修改寫進my.conf,即下面的方式三。

4.3、方式三:修改配置文件my.conf

鑑於interactive_timeout和wait_timeout影響不同交互方式下的等待空閒時間,所以我們把interactive_timeout和wait_timeout都寫進my.conf,my.conf默認在/etc下,它們的值可以根據需要自行設定,內容如下:

[mysqld]
interactive_timeout=300
wait_timeout=300

之後重啓MySQL server,systemctl restart mysqld,使用下面的方式再次查看session範圍的wait_timeout、global範圍的wait_timeout、session範圍的interactive_timeout和global範圍的interactive_timeout的值,均爲在文件/etc/my.cnf中設置的值,如下:

mysql> select @@session.wait_timeout, @@global.wait_timeout, @@session.interactive_timeout, @@global.wait_timeout;
+------------------------+-----------------------+-------------------------------+-----------------------+
| @@session.wait_timeout | @@global.wait_timeout | @@session.interactive_timeout | @@global.wait_timeout |
+------------------------+-----------------------+-------------------------------+-----------------------+
|                    300 |                   300 |                           300 |                   300 |
+------------------------+-----------------------+-------------------------------+-----------------------+

5、總結

瞭解了wait_timeout的含義,以及爲什麼會出現本文開頭提到的報錯信息,列舉了三種修改wait_timeout的方式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章