Several possibilities of Lost connection to MySQL server during query

When using Navicat to export query results, I found that the connection was disconnected after a period of time, and an error was reported: [Msg] [Exp] 2013-Lost connection to MySQL server during query

At first I thought it was caused by the setting of max_allowed_packet too small, so max_allowed_packet was increased, but the same error was reported, so the problem has nothing to do with max_allowed_packet. After the data is successfully exported later, the exported file is not as large as 12 or 3M in size, and the default value of max_allowed_packet is 16M, which is sufficient for this export.

Later, after analysis, I set the net_write_timeout parameter and exported it successfully. After the completion, I thought about it carefully and made the following summary.

An error means that the connection with mysql was disconnected during the query, and the possible reasons for the disconnection are summarized as follows:

1,mysql服务宕了
2,客户端的连接线程被kill掉了
3,在查询过程中设置了防火墙
4,当查询的结果集超过 max_allowed_packet
5,mysql的timeout参数

Let's verify one by one:
1. The mysql service is down.
During the export process, we connect to make a simple query, show global status like'uptime';
the mysql service is normal during the export process

2. The connection thread of the client is killed
. There are related settings in some MySQL, such as related pt-kill, kill the SQL that has been running for more than long time, or dba is optimizing MySQL, give this query SQL to kill
There is no correlation in this export, so this possibility is also ruled out

3. The firewall is set during the query process. During
this export process, no operation and maintenance or management personnel set up the firewall or adjusted the firewall.

4. When the result set of the query exceeds max_allowed_packet,
we have increased max_allowed_packet. You can use select * into outfile to export to a file to check whether the file size exceeds max_allowed_packet

5. The timeout parameter of mysql

mysql> show variables like '%timeout%';
+-----------------------------+----------+
| Variable_name               | Value    |
+-----------------------------+----------+
| connect_timeout             | 10       |
| delayed_insert_timeout      | 300      |
| have_statement_timeout      | YES      |
| innodb_flush_log_at_timeout | 1        |
| innodb_lock_wait_timeout    | 60       |
| innodb_rollback_on_timeout  | OFF      |
| interactive_timeout         | 28800    |
| lock_wait_timeout           | 31536000 |
| net_read_timeout            | 30       |
| net_write_timeout           | 60       |
| rpl_stop_slave_timeout      | 31536000 |
| slave_net_timeout           | 60       |
| wait_timeout                | 28800    |
+-----------------------------+----------+
13 rows in set (0.01 sec)

Let's find some of the more commonly used ones from timeout and analyze them one by one.

The official connect_timeout document is as follows:

connect_timeout: The number of seconds that the mysqld server waits for a connect packet before responding with Bad handshake. The default value is 10 seconds as of MySQL 5.0.52 and 5 seconds before that

Refers to the timeout period of the handshake during the connection process. The default is 10 seconds after 5.0.52, and the default is 5 seconds in the previous version. The basic principle of mysql should be that there is a listener thread that receives requests in a loop. When a request comes, it creates a thread (or takes it from the thread pool) to process the request. Since the mysql connection uses the TCP protocol, the TCP three-way handshake is bound to be required before. After the TCP three-way handshake is successful, the client will enter the block and wait for a message from the server. At this time, the server will create a thread (or take a thread from the thread pool) to process the request. The main verification part includes host and username password verification. We are familiar with host verification, because the host is specified when authorizing users with the grant command. User name and password authentication means that the server first generates a random number and sends it to the client. The client uses the random number and password for multiple sha1 encryption and then sends it to the server for verification. If it passes, the entire connection handshake process is completed. (Find the information after the specific handshake process and then analyze)

It can be seen that there may be various possible errors in the entire connection handshake. So this connect_timeout value refers to this timeout period. You can simply test, run the following telnet command, you will find that the client will time out and return after 10 seconds.

telnet localhost 3306

The connection status in mysql before the timeout is as follows:

256 | unauthenticated user | localhost:60595 | NULL | Connect | NULL | Reading from net | NULL

The official documents of interactive_timeout & wait_timeout are as follows:

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()).

Both wait_timeout and interactive_timeout refer to the inactive connection timeout period. When the connection thread starts, wait_timeout will be set to one of these two values ​​according to whether it is interactive or non-interactive. If we run mysql -uroot -p to log in to mysql, wait_timeout will be set to the value of interactive_timeout. If we do not perform any operation within the wait_timeout time, the timeout will be prompted when the operation is performed again, which is the mysql client will reconnect.

The test is as follows:

mysql> set global interactive_timeout=3; ##设置交互超时为3秒

Re-enter mysql, this time you can see:

mysql> show variables like '%timeout%'; ##wait_timeout已经被设置为3秒
+-----------------------------+----------+
| Variable_name               | Value    |
+-----------------------------+----------+
| connect_timeout             | 10       |
| delayed_insert_timeout      | 300      |
| innodb_flush_log_at_timeout | 1        |
| innodb_lock_wait_timeout    | 50       |
| innodb_rollback_on_timeout  | OFF      |
| interactive_timeout         | 3        |
| lock_wait_timeout           | 31536000 |
| net_read_timeout            | 30       |
| net_write_timeout           | 3        |
| rpl_stop_slave_timeout      | 31536000 |
| slave_net_timeout           | 3600     |
| wait_timeout                | 3        |
+-----------------------------+----------+

You can see that wait_timeout is set to the value of interactive_timeout, so that when we execute other commands after 3 seconds, we will be prompted as follows:

mysql> show variables like '%timeout%';
ERROR 2006 (HY000): MySQL server has gone away  ##超时重连
No connection. Trying to reconnect...
Connection id:    50
Current database: *** NONE ***
+-----------------------------+----------+
| Variable_name               | Value    |
+-----------------------------+----------+
| connect_timeout             | 10       |
| delayed_insert_timeout      | 300      |
| innodb_flush_log_at_timeout | 1        |
| innodb_lock_wait_timeout    | 50       |
| innodb_rollback_on_timeout  | OFF      |
| interactive_timeout         | 3        |
| lock_wait_timeout           | 31536000 |
| net_read_timeout            | 30       |
| net_write_timeout           | 3        |
| rpl_stop_slave_timeout      | 31536000 |
| slave_net_timeout           | 3600     |
| wait_timeout                | 3        |
+-----------------------------+----------+

The official documents of innodb_lock_wait_timeout & innodb_rollback_on_timeout are as follows:

The length of time in seconds an InnoDB transaction waits for a row lock before giving up. The default value is 50 seconds. A transaction that tries to access a row that is locked by another InnoDB transaction waits at most this many seconds for write access to the row before issuing the following error:ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

This value is for the innodb engine and is the waiting timeout time for row locks in innodb. The default is 50 seconds. If it times out, the current statement will be rolled back. If innodb_rollback_on_timeout is set, the entire transaction will be rolled back, otherwise, only the statement of the transaction waiting for row lock will be rolled back.

The test is as follows (first create a table test of the innodb engine with only one column and the column name is a):

mysql> CREATE TABLE `test` ( `a` int primary key) engine=innodb;

First insert three test data

mysql> select * from test;
+---+
| a |
+---+
| 1 |
| 2 |
| 3 |

Currently innodb_rollback_on_timeout=OFF, set innodb_lock_wait_timeout=1, we open two transactions

##Transaction 1 Add row lock

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from test where a=2 for update;
+---+
| a |
+---+
| 2 |
+---+
1 row in set (0.01 sec)

##Transaction 2, request row lock

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> delete from test where a=1;
Query OK, 1 row affected (0.00 sec)
mysql> delete from test where a=2; ##请求行锁超时
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> select * from test;
+---+
| a |
+---+
| 2 |
| 3 |
+---+
2 rows in set (0.00 sec)

mysql> begin; ##Here we directly open another transaction, the original transaction will only roll back the second statement, and the final result is that only 2 and 3 are left in the test table. If we show the rollback here, it will return Roll the entire transaction, keeping 1, 2, and 3 unchanged.

The official document of lock_wait_timeout is as follows:

This variable specifies the timeout in seconds for attempts to acquire metadata locks. The permissible values range from 1 to 31536000 (1 year). The default is 31536000.This timeout applies to all statements that use metadata locks. These include DML and DDL operations on tables, views, stored procedures, and stored functions, as well as LOCK TABLES, FLUSH TABLES WITH READ LOCK, and HANDLER statements

lock_wait_timeout is the metadata lock waiting timeout. Any statement that locks metadata will use this timeout parameter, and the default is one year. Metadata lock can participate in mysql metadata lock, in order to ensure that the transaction can be serialized, whether it is a table of myisam or innodb engine, as long as a transaction is started, the metadata lock of the operation table will be acquired. At this time, if another transaction wants to The metadata of the table is modified, it will block until the timeout.

The test is as follows:
We use a myisam engine table myisam_test to test. There is a record (1,1), now we first start a transaction, and then execute a select statement. In addition, open a session, and then perform table metadata operations, such as deleting the table, you will find that the operation is blocked until lock_wait_timeout seconds, and then prompts for a timeout.

##First session, get metadata lock

mysql> show create table myisam_test;
-----------------------------------------------------------+
| Table       | Create Table                                                                                                                                |
+-----------------------------------------------------------
| myisam_test | CREATE TABLE `myisam_test` (
  `i` int(11) NOT NULL,
  `j` int(11) DEFAULT NULL,
  PRIMARY KEY (`i`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from myisam_test;
+---+------+
| i | j    |
+---+------+
| 2 |    1 |
+---+------+
1 row in set (0.00 sec)

##Another session, delete table prompt timeout

mysql> drop table myisam_test;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

The metadata operation instructions for changing the table structure are as follows:
DROP TABLE t;
ALTER TABLE t ...;
DROP TABLE nt;
ALTER TABLE nt ...;
LOCK TABLE t ... WRITE;

The official documents of net_read_timeout & net_write_timeout are as follows:

The number of seconds to wait for more data from a connection before aborting the read. When the server is reading from the client, net_read_timeout is the timeout value controlling when to abort. When the server is writing to the client, net_write_timeout is the timeout value controlling when to abort

These two parameters work under bad network conditions. For example, I use load data infile on the client to import a large file into the database, and then use iptables to disable port 3306 of mysql. At this time, the connection status on the server side is reading from net. After waiting for net_read_timeout, I close it. connection. In the same way, when querying a large table in the program, the port is also disabled during the query process, creating a network disconnection, so that the connection status is writing to net, and then closing the connection after net_write_timeout. Slave_net_timeout is similar.

The test is as follows: I create a 120M data file data.txt. Then log in to mysql.

mysql -uroot -h 127.0.0.1 -P 3306 --local-infile=1

The import process set iptables to disable port 3306.

iptables -A INPUT -p tcp --dport 3306 -j DROP
iptables -A OUTPUT -p tcp --sport 3306 -j DROP

You can see that the connection status is reading from net, and then it is closed after net_read_timeout seconds.

to sum up

经过几个实验可以发现,
connect_timeout在握手认证阶段(authenticate)起作用
interactive_timeout 和wait_timeout在连接空闲阶段(sleep)起作用
net_read_timeout和net_write_timeout则是在连接繁忙阶段(query)或者网络出现问题时起作用。

We are exporting data, so only the net_read_timeout and net_write_timeout parameters may have an impact on us. We are exporting data, so adjust the net_write_timeout parameter. After completion, the export will be smooth.

The reference about timeout is as follows:
https://www.cnblogs.com/yum777/p/6137832.html

Guess you like

Origin blog.51cto.com/qhd2004/2535235