操作タイムアウトがないときに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 環境でアクセス許可を開く

推薦する

NodeサイトのForever+nginx導入方法例

私は最近、最も安い Tencent クラウド サーバーを購入しました。これは主に、Web テクノロジ...

CSSを使用してアダプティブスクエアを実装する方法の例

伝統的な方法は、正方形を固定形式で書くことです。長さ=幅を直接書き、次のように固定値を書きます。 。...

VUE+CanvasはシンプルなGobangゲームの全プロセスを実現します

序文レイアウトの点では、Gobang はランダムな動きを目的とするゲームよりも実装がはるかに簡単で、...

MySQLの基本操作を詳しく解説(第2部)

序文この記事には1. データベースのいくつかの主要な制約2. テーブル間の関係制約:主キー制約: 機...

子コンポーネントを通じて親コンポーネントのプロパティを変更するための Vue のさまざまな実装方法

目次序文一般的な方法1. 親コンポーネントを介して子コンポーネントの発行イベントをリッスンしてpro...

CentOS7.5 MySQLのインストールチュートリアル

1. まずシステムにmysqlがインストールされているかどうかを確認します rpm -qa | gr...

ウェブデザインスキル:中国語と英語が混在するウェブページの上位表示の問題

<br />私はこの問題で気が狂いそうです。症状は次のとおりです。 症状の説明: Int...

Linux 上での Go 環境の構築のインストールと設定の説明

Linux で Go 環境を構築するのは非常に簡単です。 1. go1.2.1.linux-386....

曇り空のアイコン効果を実現する純粋な CSS

効果効果は以下のとおりです​実装のアイデアbox-shadow プロパティを使用して、複数の灰色の円...

Vue スキャフォールディングでのレンダリングを理解する

Vue スキャフォールディングでは、エントリ ファイル main.js の新しい Vue コードに、...

テーブルの4辺を上下左右にスクロールするように固定する方法

質問:最近、プロジェクトの統計を行っていたときに、テーブルを上下にスクロールしたときにテーブルの先頭...

Tomcat セキュリティ仕様 (Tomcat セキュリティ強化と仕様)

tomcat はオープンソースの Web サーバーです。Tomcat ベースの Web は実行効率...

CSS の優先順位に関する詳細な紹介

CSS の優先順位について話す前に、CSS とは何か、CSS が何に使用されるのかを理解する必要があ...

MySQLはconnect_by_isleaf MySQLメソッドまたはストアドプロシージャに似た機能を実装します

最近、特に異常なビジネス需要があり、テーブルがあります テーブル「デモ」を作成します( `id` i...

Linux でファイルプレフィックスを一括で追加する方法

フォルダー内のすべての txt ファイルのファイル名の前に「gt_」を追加する必要があります。つまり...