Varias posibilidades de conexión perdida al servidor MySQL durante la consulta

Al usar Navicat para exportar los resultados de la consulta, descubrí que la conexión se desconectó después de un período de tiempo y se informó un error: [Msg] [Exp] 2013-Se perdió la conexión al servidor MySQL durante la consulta

Al principio pensé que se debía a que la configuración de max_allowed_packet era demasiado pequeña, por lo que se aumentó max_allowed_packet, pero se informó el mismo error, por lo que el problema no tiene nada que ver con max_allowed_packet. Una vez que los datos se exportan con éxito más tarde, el archivo exportado no tiene un tamaño de 12 o 3 M, y el valor predeterminado de max_allowed_packet es 16 M, que es suficiente para esta exportación.

Más tarde, después del análisis, configuré el parámetro net_write_timeout y lo exporté con éxito. Después de completarlo, lo pensé detenidamente e hice el siguiente resumen.

Un error significa que la conexión con mysql se desconectó durante la consulta, y las posibles razones de la desconexión se resumen a continuación:

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

Verifiquemos uno por uno:
1. El servicio mysql está inactivo.
Durante el proceso de exportación, nos conectamos para hacer una consulta simple, mostrar el estado global como 'uptime';
el servicio mysql es normal durante el proceso de exportación

2. Se mata el hilo de conexión del cliente
. Hay configuraciones relacionadas en algunos MySQL, como pt-kill relacionado, mata el SQL que se ha estado ejecutando por más de mucho tiempo, o dba está optimizando MySQL, da esta consulta SQL para matar
No existe correlación en esta exportación, por lo que también se descarta esta posibilidad

3. El firewall se establece durante el proceso de consulta Durante
este proceso de exportación, ningún personal de operación, mantenimiento o administración configuró el firewall o ajustó el firewall.

4. Cuando el conjunto de resultados de la consulta excede max_allowed_packet,
aumentamos max_allowed_packet. Puede usar select * into outfile para exportar a un archivo y verificar si el tamaño del archivo excede max_allowed_packet

5. El parámetro de tiempo de espera de 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)

Busquemos algunos de los que se utilizan con más frecuencia en el tiempo de espera y analicémoslos uno por uno.

El documento oficial connect_timeout es el siguiente:

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

Se refiere al período de tiempo de espera del protocolo de enlace durante el proceso de conexión. El valor predeterminado es 10 segundos después de 5.0.52 y el valor predeterminado es 5 segundos en la versión anterior. El principio básico de mysql debería ser que hay un hilo de escucha que recibe solicitudes en un bucle. Cuando llega una solicitud, crea un hilo (o lo toma del grupo de hilos) para procesar la solicitud. Dado que la conexión mysql usa el protocolo TCP, es probable que antes se requiera el protocolo de enlace de tres vías TCP. Después de que el protocolo de enlace de tres vías de TCP sea exitoso, el cliente ingresará al bloque y esperará un mensaje del servidor. En este momento, el servidor creará un hilo (o tomará un hilo del grupo de hilos) para procesar la solicitud. La parte de verificación principal incluye la verificación de la contraseña del nombre de usuario y del host. Estamos familiarizados con la verificación del host, porque el host se especifica al autorizar a los usuarios con el comando de concesión. La autenticación de nombre de usuario y contraseña significa que el servidor primero genera un número aleatorio y lo envía al cliente. El cliente usa el número aleatorio y la contraseña para el cifrado sha1 múltiple y luego lo envía al servidor para su verificación. Si pasa, se completa todo el proceso de reconocimiento de la conexión. (Encuentre la información después del proceso de apretón de manos específico y luego analícela)

Puede verse que puede haber varios errores posibles en todo el protocolo de enlace de la conexión. Entonces, este valor de connect_timeout se refiere a este período de tiempo de espera. Simplemente puede probar, ejecutar el siguiente comando telnet, encontrará que el cliente se agotará y regresará después de 10 segundos.

telnet localhost 3306

El estado de la conexión en mysql antes del tiempo de espera es el siguiente:

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

Los documentos oficiales de interactive_timeout y wait_timeout son los siguientes:

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

Tanto wait_timeout como interactive_timeout se refieren al período de tiempo de espera de la conexión inactiva. Cuando se inicia el hilo de conexión, wait_timeout se configurará en uno de estos dos valores según sea interactivo o no interactivo. Si ejecutamos mysql -uroot -p para iniciar sesión en mysql, wait_timeout se establecerá en el valor de interactive_timeout. Si no realizamos ninguna operación dentro del tiempo wait_timeout, el tiempo de espera se solicitará cuando la operación se realice nuevamente, que es el cliente mysql se volverá a conectar.

La prueba es la siguiente:

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

Vuelva a ingresar a mysql, esta vez puede ver:

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        |
+-----------------------------+----------+

Puede ver que wait_timeout se establece en el valor de interactive_timeout, de modo que cuando ejecutamos otros comandos después de 3 segundos, se nos pedirá lo siguiente:

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        |
+-----------------------------+----------+

Los documentos oficiales de innodb_lock_wait_timeout & innodb_rollback_on_timeout son los siguientes:

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

Este valor es para el motor innodb y es el tiempo de espera para bloqueos de fila en innodb. El valor predeterminado es 50 segundos. Si se agota el tiempo de espera, se revertirá la declaración actual. Si se establece innodb_rollback_on_timeout, la transacción completa se revertirá; de lo contrario, solo se revertirá la declaración de la transacción que espera el bloqueo de fila.

La prueba es la siguiente (primero cree una prueba de tabla del motor innodb con una sola columna y el nombre de la columna es a):

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

Primero inserte tres datos de prueba

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

Actualmente innodb_rollback_on_timeout = OFF, establece innodb_lock_wait_timeout = 1, abrimos dos transacciones

## Transacción 1 Agregar bloqueo de fila

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)

## Transacción 2, solicitar bloqueo de fila

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; ## Aquí abrimos directamente otra transacción, la transacción original solo revertirá la segunda declaración, y el resultado final es que solo quedan 2 y 3 en la tabla de prueba. Si mostramos la reversión aquí, devolverá Lanza toda la transacción, manteniendo 1, 2 y 3 sin cambios.

El documento oficial de lock_wait_timeout es el siguiente:

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 es el tiempo de espera del bloqueo de metadatos. Cualquier declaración que bloquee los metadatos utilizará este parámetro de tiempo de espera, y el valor predeterminado es un año. El bloqueo de metadatos puede participar en el bloqueo de metadatos de mysql, con el fin de garantizar que la transacción se pueda serializar, ya sea una tabla de myisam o un motor innodb, siempre que se inicie una transacción, se adquirirá el bloqueo de metadatos de la tabla de operaciones. En este momento, si otra transacción lo desea Se modifican los metadatos de la tabla, se bloqueará hasta el tiempo de espera.

La prueba es la siguiente:
Usamos una tabla de motor myisam myisam_test para probar. Hay un registro (1,1), ahora primero comenzamos una transacción y luego ejecutamos una instrucción de selección. Además, abra una sesión y luego realice operaciones de metadatos de la tabla, como eliminar la tabla, encontrará que la operación está bloqueada hasta lock_wait_timeout segundos, y luego solicita un tiempo de espera.

## Primera sesión, obtén bloqueo de metadatos

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)

## Otra sesión, eliminar el tiempo de espera de la solicitud de la tabla

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

Las instrucciones de operación de metadatos para cambiar la estructura de la tabla son las siguientes:
DROP TABLE t;
ALTER TABLE t ...;
DROP TABLE nt;
ALTER TABLE nt ...;
LOCK TABLE t ... WRITE;

Los documentos oficiales de net_read_timeout y net_write_timeout son los siguientes:

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

Estos dos parámetros funcionan en malas condiciones de red. Por ejemplo, utilizo el archivo de datos de carga en el cliente para importar un archivo grande a la base de datos, y luego uso iptables para deshabilitar el puerto 3306 de mysql. En este momento, el estado de la conexión en el lado del servidor es leer desde la red. Después de esperar net_read_timeout, lo cierro. conexión. De la misma manera, al consultar una tabla grande en el programa, el puerto también se deshabilita durante el proceso de consulta, creando una desconexión de la red, de modo que el estado de la conexión es escribir en la red y luego cerrar la conexión después de net_write_timeout. Slave_net_timeout es similar.

La prueba es la siguiente: creo un archivo de datos de 120M data.txt. Luego inicie sesión en mysql.

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

El proceso de importación configuró iptables para deshabilitar el puerto 3306.

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

Puede ver que el estado de la conexión se lee desde la red y luego se cierra después de net_read_timeout segundos.

para resumir

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

Estamos exportando datos, por lo que solo los parámetros net_read_timeout y net_write_timeout pueden tener un impacto en nosotros. Estamos exportando datos, así que ajusta el parámetro net_write_timeout. Una vez completada, la exportación será fluida.

La referencia sobre el tiempo de espera es la siguiente:
https://www.cnblogs.com/yum777/p/6137832.html

Supongo que te gusta

Origin blog.51cto.com/qhd2004/2535235
Recomendado
Clasificación