web-dev-qa-db-ja.com

小さなトラフィックサーバーでのmysql接続タイムアウト

接続がタイムアウトしないようにMySQLを設定するにはどうすればよいですか?そして、wait_timeoutinteractive_timeoutなどの変数の現在の設定が何であるかを確認するにはどうすればよいですか?これらの変数が以下に示す構成。

ここに状況があります:

低(マイクロ)トラフィックのWebサーバーは、数週間データベーストランザクションを受信しないことがあります。 Mysqlは、いくつかのプライベートWebアプリケーションと同じサーバーボックスで実行されています。接続文字列にautoReconnect=trueを設定しましたが、数日後にチェックすると、Webアプリケーションがデータベースに接続できないことに常に気付き、catalina.outログを開くと、次のようになります。

Caused by: Java.net.SocketException: Broken pipe
    at Java.net.SocketOutputStream.socketWrite0(Native Method) ~[na:1.7.0_75]
    at Java.net.SocketOutputStream.socketWrite(SocketOutputStream.Java:113) ~[na:1.7.0_75]
    at Java.net.SocketOutputStream.write(SocketOutputStream.Java:159) ~[na:1.7.0_75]
    at Java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.Java:82) ~[na:1.7.0_75]
    at Java.io.BufferedOutputStream.flush(BufferedOutputStream.Java:140) ~[na:1.7.0_75]
    at com.mysql.jdbc.MysqlIO.send(MysqlIO.Java:3969) ~[mysql-connector-Java-5.1.27.jar:na]
    ... 111 common frames omitted

その後、Tomcatを再起動すると、webappsはデータベース接続を再び確立できますが、問題が繰り返し発生し、長期間かかるため、パイプ切断エラーがいつ再発生するかを確認するために待機日数をテストすることは妥当ではありません。

このリンクのチュートリアル を含む、mysqlの最大タイムアウトの設定に関する多くの投稿を読みましたが、私のマシンのconfファイルで定義されていない変数について説明しています。たとえば、問題のサーバー上のmysql構成ファイルは次のとおりです。

/etc/my.cnfは:

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# Settings user and group are ignored when systemd is used.
# If you need to run mysqld under a different user or group,
# customize your systemd unit file for mariadb according to the
# instructions in http://fedoraproject.org/wiki/Systemd

[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid

#
# include all files from the config directory
#
!includedir /etc/my.cnf.d

ご覧のとおり、ファイルにはmy.cnf.dフォルダの内容が含まれています。これは次の3つのファイルです。

/etc/my.cnf.d/client.cnfは:

#
# These two groups are read by the client library
# Use it for options that affect all clients, but not the server
#

[client]

# This group is not read by mysql client library,
# If you use the same .cnf file for MySQL and MariaDB,
# use it for MariaDB-only client options
[client-mariadb]

/etc/my.cnf.d/mysql-clients.cnfは:

#
# These groups are read by MariaDB command-line tools
# Use it for options that affect only one utility
#

[mysql]

[mysql_upgrade]

[mysqladmin]

[mysqlbinlog]

[mysqlcheck]

[mysqldump]

[mysqlimport]

[mysqlshow]

[mysqlslap]

/etc/my.cnf.d/server.cnfは:

#
# These groups are read by MariaDB server.
# Use it for options that only the server (but not clients) should see
#
# See the examples of server my.cnf files in /usr/share/mysql/
#

# this is read by the standalone daemon and embedded servers
[server]

# this is only for the mysqld standalone daemon
[mysqld]

# this is only for embedded server
[embedded]

# This group is only read by MariaDB-5.5 servers.
# If you use the same .cnf file for MariaDB of different versions,
# use this group for options that older servers don't understand
[mysqld-5.5]

# These two groups are only read by MariaDB servers, not by MySQL.
# If you use the same .cnf file for MySQL and MariaDB,
# you can put MariaDB-only options here
[mariadb]

[mariadb-5.5]

Tomcatのserver.xmlは、タイムアウトを20秒(20,000ミリ秒)と定義しています。これは明らかにMySQLのグローバルwait_timeoutを参照していません。ただし、/opt/Tomcat/conf/server.xmlのタイムアウトへの唯一の参照は次のとおりです。

<Connector port="8082" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8445" />

20000 connectionTimeout設定がミリ秒を指していることを確認しました このリンクを読むことにより

Spring MVCアプリケーションレベルの設定について この他の投稿 を読みましたが、答えはmy.cnf設定よりも小さいアプリケーションレベル変数の設定を参照しています。上記のmy.cnfおよびインクルードファイルのバージョンにないサーバーレベルの設定が少なくとも表示されない場合は、アプリケーションレベルをいじるのをためらいます。それにもかかわらず、Spring mvc web app xml configのdataSource定義は次のとおりです。

<context:property-placeholder location="classpath:spring/data-access.properties" system-properties-mode="OVERRIDE"/>

<!-- DataSource configuration for the Tomcat jdbc connection pool -->
<bean id="dataSource" class="org.Apache.Tomcat.jdbc.pool.DataSource"
      p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.url}"
      p:username="${jdbc.username}" p:password="${jdbc.password}"/>  

最後に、上記のdataSource Beanで参照される変数は、次のようにプロパティファイル(data-access.properties)で定義されます。

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/dbasename?autoReconnect=true
jdbc.username=username
jdbc.password=password
hibernate.dialect=org.hibernate.dialect.MySQLDialect
jpa.database=MYSQL
jpa.showSql=false

接続がタイムアウトしないようにMySQLを設定するにはどうすればよいですか?また、wait_timeoutinteractive_timeoutなどの変数の現在の設定が何であるかを確認するにはどうすればよいですか?それらが構成ファイルにない場合上に示しました。


編集:


@RickJamesの提案に従って、/etc/my.cnfを次のように編集しました。

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
wait_timeout = 2147483
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# Settings user and group are ignored when systemd is used.
# If you need to run mysqld under a different user or group,
# customize your systemd unit file for mariadb according to the
# instructions in http://fedoraproject.org/wiki/Systemd

[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid

#
# include all files from the config directory
#
!includedir /etc/my.cnf.d

次に、systemctl stop mariadb.serviceの後にsystemctl start mariadb.serviceを入力して、データベースを停止して再起動しました。しかし、その後MySQLにログインし、show variables like '%timeout%';と入力して@Veraceの提案に従っていると、結果は次のようになりました。

+----------------------------+----------+
| Variable_name              | Value    |
+----------------------------+----------+
| connect_timeout            | 10       |
| deadlock_timeout_long      | 50000000 |
| deadlock_timeout_short     | 10000    |
| delayed_insert_timeout     | 300      |
| innodb_lock_wait_timeout   | 50       |
| innodb_rollback_on_timeout | OFF      |
| interactive_timeout        | 28800    |
| lock_wait_timeout          | 31536000 |
| net_read_timeout           | 30       |
| net_write_timeout          | 60       |
| slave_net_timeout          | 3600     |
| thread_pool_idle_timeout   | 60       |
| wait_timeout               | 28800    |
+----------------------------+----------+
13 rows in set (0.00 sec)

何が悪いのですか?

1
CodeMed

そこに任意の時間接続して座ることは悪い習慣です。 wait_timeout 30(秒)のようなものにして、切断を処理するコードを記述します。 MySQLへの再接続は非常に高速であるため、パフォーマンスの問題ではありません。アプリが(たとえば)30秒間アイドル状態の場合、エラーが発生することが予想され、再接続する必要があります。

ネットワークの不具合などが原因で接続が切断される可能性があることに注意してください。したがって、とにかく切断のためにコーディングする必要があります。

編集

InnoDBでAUTORECONNECTを使用しないでください。厄介な不具合が発生する可能性があります。代わりに、各クエリの後に「接続されていない」エラーをキャッチし、トランザクションを再開します。別のアプローチは、長いアイドル期間から戻ってくる可能性があるときに「ping」を実行することです。

3
Rick James

あなたが書いた

また、wait_timeoutやinteractive_timeoutなどの変数の現在の設定を確認するにはどうすればよいですか?

以下の「変数の表示」を使用(MySQLクライアントから)

mysql> show variables like '%timeout%';
+-----------------------------+----------+
| 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         | 28800    |
| lock_wait_timeout           | 31536000 |
| net_read_timeout            | 30       |
| net_write_timeout           | 60       |
| rpl_stop_slave_timeout      | 31536000 |
| slave_net_timeout           | 3600     |
| wait_timeout                | 28800    |
+-----------------------------+----------+
12 rows in set (0.00 sec)
mysql> 

wait_timeoutは28800(8時間)に設定されています

あなたも書いた:

これらの変数は、以下に示す構成で定義されていないとします。

ここで起こっていることは、MySQLの動作を管理する〜500変数のすべてがmy.cnfで指定されているわけではないということです。そのファイルは主にデフォルトを変更するために使用されます。

最後に、あなたは書きました:

では、接続がタイムアウトしないようにMySQLを設定するにはどうすればよいですか?

から ここ

あなたが持っている

wait_timeout

Command-Line Format --wait_timeout=#
System Variable Name    wait_timeout
Variable Scope  Global, Session
Dynamic Variable    Yes
Permitted Values (Windows)  Type    integer
Default 28800
Min Value   1
Max Value   2147483      <<<<============== ****WINDOWS****
Permitted Values (Other)    Type    integer
Default 28800
Min Value   1
Max Value   31536000   <<<<================ ****UNIX***

「最大値」-たまたま1年間の秒数です-したがって、タイムアウトしないように設定することはできませんが、1年間トラフィックがないサイトはほとんど価値がないことをお勧めします。 :-) @RickJamesの提案に従って[mysql]セクションに値を設定します。

1
Vérace