Lost connection to MySQL server during query的几种可能

在使用navicat导出查询结果时,发现一段时间后就断开连接了,报错:[Msg] [Exp] 2013 - Lost connection to MySQL server during query

开始以为是max_allowed_packet设置过小导致,所以加大了max_allowed_packet,但是还是一样报错,因此问题跟max_allowed_packet没有关系。后面成功导出数据后,导出的文件也不大12、3M大小,而max_allowed_packet默认值是16M,完全够这次导出使用。

后来经过分析,我这设置了net_write_timeout参数后,成功导出,完成后,仔细想了一下,做了如下的总结。

报错的意思是在查询的过程中与mysql断开了连接,而可能产生断开连接的原因总结如下:

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

下面我们挨个验证一下:
1,mysql服务宕了
在导出的过程中,我们连接上去做个简单查询,show global status like 'uptime';
本次导出过程中mysql服务正常

2,客户端的连接线程被kill掉了
有些mysql中有相关的设置,比如有相关的pt-kill,kill掉运行时间超过多长的sql,或是有dba在优化mysql,把这个查询sql给kill了
本次导出中并没有相关,因此也排除这种可能

3,在查询过程中设置了防火墙
本次导出过程中,并没有运维或是管理人员设置防火墙,或是调整防火墙

4.クエリの結果セットがmax_allowed_pa​​cket
超えると、max_allowed_pa​​cketが増えました。select* to outfileを使用してファイルにエクスポートし、ファイルサイズがmax_allowed_pa​​cketを超えているかどうかを確認できます。

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

タイムアウトから一般的に使用されるものをいくつか見つけて、1つずつ分析してみましょう。

公式のconnect_timeoutドキュメントは次のとおりです。

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

接続プロセス中のハンドシェイクのタイムアウト期間を指します。デフォルトは5.0.52以降の10秒、以前のバージョンでは5秒です。mysqlの基本原則は、ループでリクエストを受信するリスナースレッドが存在することであり、リクエストが来ると、スレッドを作成(またはスレッドプールから取得)してリクエストを処理します。mysql接続はTCPプロトコルを使用するため、以前はTCP 3ウェイハンドシェイクが必要になるはずです。TCP 3ウェイハンドシェイクが成功した後、クライアントはブロックに入り、サーバーからのメッセージを待ちます。このとき、サーバーはリクエストを処理するためのスレッドを作成(またはスレッドプールからスレッドを取得)します。主な検証部分には、ホストとユーザー名のパスワード検証が含まれます。ホストはgrantコマンドでユーザーを承認するときに指定されるため、ホストの検証についてはよく知っています。ユーザー名とパスワードによる認証は、サーバーが最初に乱数を生成してクライアントに送信することを意味します。クライアントは、乱数とパスワードを使用して複数のsha1暗号化を行い、検証のためにサーバーに送信します。成功すると、接続ハンドシェイクプロセス全体が完了します。(特定のハンドシェイクプロセスの後に情報を見つけて分析します)

接続ハンドシェイク全体でさまざまなエラーが発生する可能性があることがわかります。したがって、このconnect_timeout値はこのタイムアウト期間を指します。簡単にテストして次のtelnetコマンドを実行すると、クライアントがタイムアウトして10秒後に戻ることがわかります。

telnet localhost 3306

タイムアウト前のmysqlの接続ステータスは次のとおりです。

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

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

wait_timeoutとinteractive_timeoutはどちらも、非アクティブな接続タイムアウト期間を参照します。接続スレッドが開始すると、wait_timeoutは、インタラクティブか非インタラクティブかに応じて、これら2つの値のいずれかに設定されます。mysql -uroot -pを実行してmysqlにログインすると、wait_timeoutはinteractive_timeoutの値に設定されます。wait_timeout時間内に何の操作も実行しない場合、操作が再度実行されると、mysqlクライアントが再接続するときにタイムアウトが要求されます。

テストは次のとおりです。

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

mysqlを再入力します。今回は次のようになります。

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

wait_timeoutがinteractive_timeoutの値に設定されていることがわかります。3秒後に他のコマンドを実行すると、次のようにプロンプ​​トが表示されます。

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

innodb_lock_wait_timeoutおよびinnodb_rollback_on_timeoutの公式ドキュメントは次のとおりです。

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

この値はinnodbエンジン用であり、innodbでの行ロックの待機タイムアウト時間であり、デフォルトは50秒です。タイムアウトになると、現在のステートメントがロールバックされます。innodb_rollback_on_timeoutが設定されている場合、トランザクション全体がロールバックされます。それ以外の場合は、行ロックを待機しているトランザクションのステートメントのみがロールバックされます。

テストは次のとおりです(最初に列が1つだけで、列名がaのinnodbエンジンのテーブルテストを作成します)。

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

最初に3つのテストデータを挿入する

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

現在innodb_rollback_on_timeout = OFF、innodb_lock_wait_timeout = 1に設定、2つのトランザクションを開く

##トランザクション1行ロックを追加する

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)

##トランザクション2、リクエスト行ロック

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; ##ここで別のトランザクションを直接開きます。元のトランザクションは2番目のステートメントのみをロールバックし、最終結果は2と3のみがテストテーブルに残っています。ここでロールバックを表示すると、返されます1、2、および3を変更せずに、トランザクション全体をロールします。

lock_wait_timeoutの公式ドキュメントは次のとおりです。

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はメタデータロック待機タイムアウトです。メタデータをロックするステートメントはすべてこのタイムアウトパラメータを使用し、デフォルトは1年で​​す。メタデータロックはmysqlメタデータロックに参加でき、トランザクションが確実にシリアライズできるようにするために、トランザクションが開始されている限り、トランザクションがmyisamまたはinnodbエンジンのテーブルであっても、オペレーションテーブルのメタデータロックが取得されます。このとき、別のトランザクションがテーブルのメタデータが変更され、タイムアウトになるまでブロックされます。

テストは次のとおりです。テストには
、myisamエンジンテーブルmyisam_testを使用します。レコード(1,1)があります。最初にトランザクションを開始してから、selectステートメントを実行します。また、セッションを開いてから、テーブルの削除などのテーブルメタデータ操作を実行すると、lock_wait_timeout秒まで操作がブロックされ、タイムアウトのプロンプトが表示されます。

##最初のセッション、メタデータロックを取得

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)

##別のセッション、テーブルプロンプトタイムアウトの削除

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

テーブル構造を変更するためのメタデータ操作手順は次のとおりです
。DROPTABLE t;
ALTER TABLE t ...;
DROP TABLE nt;
ALTER TABLE nt ...;
LOCK TABLE t ... WRITE;

net_read_timeoutおよびnet_write_timeoutの公式ドキュメントは次のとおりです。

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

これら2つのパラメーターは、ネットワークの状態が悪いときに機能します。たとえば、クライアントでload data infileを使用して大きなファイルをデータベースにインポートし、次にiptablesを使用してmysqlのポート3306を無効にします。このとき、サーバー側の接続ステータスはネットから読み取っています。net_read_timeoutを待った後、それを閉じます。接続。同様に、プログラムで大きなテーブルにクエリを実行すると、クエリプロセス中にポートが無効になり、ネットワーク切断が発生するため、接続ステータスがnetに書き込まれ、net_write_timeoutの後に接続が閉じます。Slave_net_timeoutも同様です。

テストは次のとおりです。120Mのデータファイルdata.txtを作成します。次に、mysqlにログインします。

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

インポートプロセスは、ポート3306を無効にするようにiptablesを設定しました。

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

接続ステータスがネットから読み取り中であり、net_read_timeout秒後に閉じられていることがわかります。

総括する

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

データをエクスポートするので、net_read_timeoutおよびnet_write_timeoutパラメーターのみが影響を与える可能性があります。データをエクスポートするので、net_write_timeoutパラメーターを調整します。完了後、エクスポートはスムーズになります。

タイムアウトに関するリファレンスは次のとおりです。https
//www.cnblogs.com/yum777/p/6137832.html

おすすめ

転載: blog.51cto.com/qhd2004/2535235