操作タイムアウトがないときにMySQLサーバーがアクティブに切断される問題を解決します

操作タイムアウトがないときにMySQLサーバーがアクティブに切断される問題を解決します

MySQL サービスを使用する場合、通常の状況では、MySQL のタイムアウト設定は 8 時間 (28800 秒) です。つまり、接続が 8 時間操作されない場合、MySQL は積極的に接続を切断します。接続が再度クエリを実行しようとすると、「MySQL サーバーが切断されました」というエラーが報告されます。ただし、MySQL サーバーの設定によっては、多くの場合、より多くの接続が利用できるように、接続タイムアウトが短縮されることがあります。設定が異常で、非常に短い 30 秒になる場合があり、その場合はクライアントが何らかの操作を行って、MySQL がアクティブに切断されないようにする必要があります。

MySQLのタイムアウトを表示

クライアント ツールまたは Mysql コマンド ライン ツールを使用して、「%timeout%」などのグローバル変数を表示すると、タイムアウトに関連するプロパティが表示されます。ここでは、docker を使用してテスト環境をシミュレートします。

mysql> '%timeout%' のような変数を表示します。 
+-----------------------------+----------+
| 変数名 | 値 |
+-----------------------------+----------+
| 接続タイムアウト | 10 |
| 遅延挿入タイムアウト | 300 |
| ステートメントタイムアウトがある | はい |
| innodb_flush_log_at_timeout | 1 |
| innodb_lock_wait_timeout | 50 |
| innodb_rollback_on_timeout | オフ |
| インタラクティブタイムアウト | 30 |
| ロック待機タイムアウト | 31536000 |
| ネット読み取りタイムアウト | 30 |
| ネット書き込みタイムアウト | 60 |
| rpl_stop_slave_timeout | 31536000 |
| スレーブネットタイムアウト | 60 |
| 待機タイムアウト | 30 |
+-----------------------------+----------+
13行セット

wait_timeout: 非対話型接続を閉じる前にサーバーがアクティビティを待機する秒数。これは、プロジェクトでプログラムを呼び出す時間です。

interactive_timeout: 対話型接続を閉じる前にサーバーがアクティビティを待機する秒数。これは、cmd などのローカル マシンで MySQL クライアントを開いた時間です。

pymysql によるクエリ

データベースにランダムテーブルを作成し、2つのデータを挿入しました

mysql> person から * を選択します。
+----+------+-----+
| ID | 名前 | 年齢 |
+----+------+-----+
| 1 | 陽 | 18 |
| 2 | ファン | 16 |
+----+------+-----+
2行セット

pymysqlライブラリを使ってクエリを実行します。とても簡単です

#コーディング:utf-8
pymysqlをインポートする

デフmytest():
  接続 = pymysql.connect(
  ホスト='localhost',
  ポート=3306、
  ユーザー='root'、
  パスワード='123456',
  db='mytest',
  文字セット='utf8')

  カーソル = connection.cursor()
  cursor.execute("人から*を選択")
  データ = カーソル.fetchall()
  カーソルを閉じる()
  データ内のiについて:
    印刷(i)
  カーソルを閉じる()
  接続を閉じる()

__name__ == '__main__' の場合:
  マイテスト()

正しい結果が得られる

(1、「陽」、18)

(2、「ファン」、16)

接続タイムアウト後のクエリ

リンク作成後、すぐにクエリが実行され、そのタイムアウト期間を超えていないため、上記の結果が正常に得られます。しばらくスリープすると、どのような効果があるかを確認します。

#コーディング:utf-8

pymysqlをインポートする
インポート時間


デフmytest():
  接続 = pymysql.connect(
  ホスト='localhost',
  ポート=3306、
  ユーザー='root'、
  パスワード='123456',
  db='mytest',
  文字セット='utf8')
  カーソル = connection.cursor()
  cursor.execute("人から*を選択")
  データ = カーソル.fetchall()
  データ内のiについて:
    印刷(i)
  カーソルを閉じる()

  時間.睡眠(31)
  カーソル = connection.cursor()
  cursor.execute("人から*を選択")
  data2 = カーソル.fetchall()
  データ2のiの場合:
    印刷(i)
  カーソルを閉じる()
  接続を閉じる()

__name__ == '__main__' の場合:
  マイテスト()

ここでは2つのクエリが実行されました。mysqlのwait_timeoutを30秒に設定していたため、最初のクエリの後に31秒間停止し、mysqlサービスが作成した接続から積極的に切断されるようにしました。結果は次のとおりです。

(1、「陽」、18)
(2、「ファン」、16)
トレースバック(最新の呼び出しが最後):
 ファイル "F:/python/python3Test/mysqltest.py"、行 29、<module>
  マイテスト()
 ファイル「F:/python/python3Test/mysqltest.py」、行 22、mytest
  cursor.execute("人から*を選択")
 ...
 ...
 ファイル "C:\Python35\lib\site-packages\pymysql\connections.py"、行 702、_read_bytes 内
  CR.CR_SERVER_LOST、「クエリ中に MySQL サーバーへの接続が失われました」
pymysql.err.OperationalError: (2013、「クエリ中に MySQL サーバーへの接続が失われました」)

プロセスは終了コード 1 で終了しました

31 秒間停止した後、再度接続を使用してクエリを実行すると、2013 の「クエリ中に MySQL サーバーへの接続が失われました」というエラーがスローされることがわかります。

解決

解決策は 2 つあります。ここでのタイムアウトは、指定された時間内に操作が行われなかったために発生するため、MySQL は積極的に接続を閉じます。pymysql 接続オブジェクトには、接続が有効かどうかを確認する ping() メソッドがあります。各クエリ操作の前に ping() メソッドを実行します。このメソッドにはデフォルトで reconnect パラメータがあり、デフォルトでは True になっています。接続が失われた場合は再接続されます。

#コーディング:utf-8

pymysqlをインポートする
インポート時間


デフmytest():
  接続 = pymysql.connect(
  ホスト='localhost',
  ポート=3306、
  ユーザー='root'、
  パスワード='123456',
  db='mytest',
  文字セット='utf8')
  接続.ping()
  カーソル = connection.cursor()
  cursor.execute("人から*を選択")
  データ = カーソル.fetchall()
  データ内のiについて:
    印刷(i)
  カーソルを閉じる()
  
  時間.睡眠(31)
  接続.ping()
  カーソル = connection.cursor()
  cursor.execute("人から*を選択")
  data2 = カーソル.fetchall()
  データ2のiの場合:
    印刷(i)
  カーソルを閉じる()
  接続を閉じる()

__name__ == '__main__' の場合:
  マイテスト()

別のスレッドを使用して ping() 操作を継続的に実行しようとしましたが、これを行うと接続が失われ、後続の操作を実行できなくなります。私はこの問題についてさらに研究するつもりです。

#コーディング:utf-8

pymysqlをインポートする
インポート時間
インポートスレッド
インポート トレースバック

定義ping(接続):
  真の場合:
    試す:      
      接続ping()
    を除外する:
      印刷(traceback.format_exc())
    ついに:
      時間.睡眠(1)

デフmytest():
  接続 = pymysql.connect(
  ホスト='localhost',
  ポート=3306、
  ユーザー='root'、
  パスワード='123456',
  db='mytest',
  文字セット='utf8')
  カーソル = connection.cursor()
  # ここでは動作しません。実行する前にカーソルの実行を待つ必要があります。 # th = threading.Thread(target=ping, args=(connection,))
  # th.setDaemon(True)
  # th.start()
  cursor.execute("人から*を選択")
  データ = カーソル.fetchall()
  データ内のiについて:
    印刷(i)
  カーソルを閉じる()

  # ここでスレッドを開始できます th = threading.Thread(target=ping, args=(connection,))
  th.setDaemon(True)
  th.start()
  
  時間.睡眠(31)
  カーソル = connection.cursor()
  cursor.execute("人から*を選択")
  data2 = カーソル.fetchall()
  データ2のiの場合:
    印刷(i)
  カーソルを閉じる()
  接続を閉じる()

__name__ == '__main__' の場合:
  マイテスト()

もう1つの方法は、接続プールを使用することです。これは、指定された数の利用可能な接続を保持し、クエリ操作ごとに有効な接続を再取得します。Pymysql自体には接続プール機能がないため、DBUtilsを使用する必要があります。

#コーディング:utf-8
pymysqlをインポートする
インポート時間
DBUtils.PooledDB から PooledDB、SharedDBConnection をインポートします


デフmytest():
  プール = PooledDB(
    作成者=pymysql、
    # 初期化時に、接続プールは少なくともアイドル接続を作成します。0 は作成しないことを意味します。maxconnections=3、 
    # 接続プール内のアイドル接続の最大数。0 および None は制限なしを示します。mincached=2、
    # 接続プール内の共有接続の最大数。0 または None はすべてが共有されることを意味します (実際には役に立ちません)
    最大キャッシュ=5、    
    最大共有数=3、
    ホスト='localhost',
    ポート=3306、
    ユーザー='root'、
    パスワード='123456',
    db='mytest',
    文字セット='utf8'
  )
  接続 = pool.connection()
  カーソル = connection.cursor()
  cursor.execute("人から*を選択")
  データ = カーソル.fetchall()
  データ内のiについて:
    印刷(i)

  時間.睡眠(40)
  cursor.execute("人から*を選択")
  data2 = カーソル.fetchall()
  データ2のiの場合:
    印刷(i)
  カーソルを閉じる()
  接続を閉じる()

__name__ == '__main__' の場合:
  マイテスト()

この方法では結果を正しく取得できますが、実際のプロジェクトでは使用されません。代わりに、クエリ ステートメントの実行後に接続を閉じる必要があります。ここでの接続を閉じることは、実際に接続を閉じることではなく、他のユーザーが使用できるように接続を接続プールに返すだけであることに注意してください。

#コーディング:utf-8
pymysqlをインポートする
インポート時間
DBUtils.PooledDB から PooledDB、SharedDBConnection をインポートします


デフmytest():
  プール = PooledDB(
    作成者=pymysql、
    最大接続数=3、
    # 初期化時に、接続プールは少なくともアイドル接続を作成します。0はmincached=2がないことを意味します。
    # 接続プール内のアイドル接続の最大数。0 および None は制限なしを示します。maxcached=5,
    # 接続プール内の共有接続の最大数。0 または None はすべて共有されることを意味します (実際には役に立ちません)
    最大共有数=3、
    ホスト='localhost',
    ポート=3306、
    ユーザー='root'、
    パスワード='123456',
    db='mytest',
    文字セット='utf8'
  )
  接続 = pool.connection()
  カーソル = connection.cursor()
  cursor.execute("人から*を選択")
  データ = カーソル.fetchall()
  データ内のiについて:
    印刷(i)
  カーソルを閉じる()
  # 接続を閉じると、実際には接続が閉じられるわけではなく、接続を接続プールに返すだけです。connection.close()

  時間.睡眠(40)
  接続 = pool.connection()
  カーソル = connection.cursor()
  cursor.execute("人から*を選択")
  data2 = カーソル.fetchall()
  データ2のiの場合:
    印刷(i)
  カーソルを閉じる()
  接続を閉じる()

__name__ == '__main__' の場合:
  マイテスト()

操作タイムアウトがないときにMySQLサーバーがアクティブに切断される問題を解決する方法に関する上記の記事は、編集者があなたと共有するすべての内容です。これが参考になることを願っており、123WORDPRESS.COMをサポートしていただければ幸いです。

以下もご興味があるかもしれません:
  • WeChatサーバーにリクエストするミニプログラムサーバーのタイムアウトの解決策
  • PHP での curl および soap リクエスト サービスのタイムアウト問題の解決方法
  • Java の非同期マルチスレッド タイムアウトによって発生するサービス例外についての簡単な説明
  • Nginxサーバーでタイムアウトを設定する方法の詳細な説明
  • 構成された DNS サーバーが応答しないため、Win7 システム ログに「ドメイン名」の名前解決のタイムアウトが期限切れになったことが示されます。
  • ORA-12170 TNS の解決策: Oracle リモート サーバーへの接続時に接続タイムアウトが発生する
  • FileZilla を使用してサーバーに接続するとタイムアウトが発生する
  • SNMP4J サーバー接続タイムアウト問題の解決策

<<:  ElementUI el-select の過剰なデータに対する解決策についての簡単な説明

>>:  MySQL を使用してポート 3306 を開いたり変更したり、Ubuntu/Linux 環境でアクセス許可を開く

推薦する

JavaScript で実装された 7 つのソート アルゴリズムの概要 (推奨!)

目次序文バブルソート基本アルゴリズム2 番目の書き方は、基本的なアルゴリズムに基づいて改良されていま...

Vue プロジェクトで Baidu Map API を使用する方法

目次1. Baidu Map Open Platformにアカウントを登録してログインする2. 必要...

mysql-connector-java.jar パッケージのダウンロード プロセスの詳細な説明

mysql-connector-java.jar パッケージのチュートリアルをダウンロードします: ...

大きな MySQL テーブルに列を追加する方法

質問は https://www.zhihu.com/question/440231149 から参照さ...

MySQLのメモリ使用量を表示する方法の詳細な説明

序文この記事では主にMySQLのメモリ使用量に関する関連コンテンツを紹介し、皆さんの参考と学習のため...

Linuxのファイルとフォルダの権限を操作する方法

Linux のファイル権限まず、現在のディレクトリ内のファイルの内容を確認しましょう。 ls -l ...

Dockerでの接続例外中のエラーを解決する

Docker を初めて使い始めると、通常とは異なる問題に遭遇して、必然的に混乱してしまいます。大丈夫...

MySQL 8.0 のインデックス スキップ スキャン

序文MySQL 8.0.13 では、インデックス スキップ スキャン (インデックス ジャンプ スキ...

Navicat for MySql ビジュアルインポート CSV ファイル

この記事では、参考までに、Navicat for MySql の CSV ファイルのビジュアルインポ...

入力要素 [type="file"] を使用する場合のスタイルのカスタマイズとブラウザの互換性の問題に関する議論

この2日間、Baixing.comの筆記試験問題を解いているときに、このような問題に遭遇しました。H...

Windows ホストと Docker コンテナに共有フォルダを設定してマウントする手順

Docker コンテナ内のプログラムは、ホスト ディレクトリ内のデータにアクセスして呼び出す必要があ...

ニューススタイルのウェブサイトデザイン例25選

bmi ボイジャーピッチフォークアルスター食料品店チャウ真/斜めポスタこれは偽のDIYですクリエイテ...

IE6のバグと修正は予防戦略です

元記事:究極の IE6 チートシート: 25 以上の Internet Explorer 6 のバグ...