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__' の場合: マイテスト() 正しい結果が得られる
接続タイムアウト後のクエリ リンク作成後、すぐにクエリが実行され、そのタイムアウト期間を超えていないため、上記の結果が正常に得られます。しばらくスリープすると、どのような効果があるかを確認します。 #コーディング: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をサポートしていただければ幸いです。 以下もご興味があるかもしれません:
|
<<: ElementUI el-select の過剰なデータに対する解決策についての簡単な説明
>>: MySQL を使用してポート 3306 を開いたり変更したり、Ubuntu/Linux 環境でアクセス許可を開く
例: <html> <ヘッド> <スタイル タイプ="tex...
目次序文バブルソート基本アルゴリズム2 番目の書き方は、基本的なアルゴリズムに基づいて改良されていま...
目次1. Baidu Map Open Platformにアカウントを登録してログインする2. 必要...
mysql-connector-java.jar パッケージのチュートリアルをダウンロードします: ...
質問は https://www.zhihu.com/question/440231149 から参照さ...
序文この記事では主にMySQLのメモリ使用量に関する関連コンテンツを紹介し、皆さんの参考と学習のため...
Linux のファイル権限まず、現在のディレクトリ内のファイルの内容を確認しましょう。 ls -l ...
Docker を初めて使い始めると、通常とは異なる問題に遭遇して、必然的に混乱してしまいます。大丈夫...
序文MySQL 8.0.13 では、インデックス スキップ スキャン (インデックス ジャンプ スキ...
この記事では、参考までに、Navicat for MySql の CSV ファイルのビジュアルインポ...
この2日間、Baixing.comの筆記試験問題を解いているときに、このような問題に遭遇しました。H...
Docker コンテナ内のプログラムは、ホスト ディレクトリ内のデータにアクセスして呼び出す必要があ...
bmi ボイジャーピッチフォークアルスター食料品店チャウ真/斜めポスタこれは偽のDIYですクリエイテ...
1. MMMの紹介: MMM は、Multi-Master Replication Manager...
元記事:究極の IE6 チートシート: 25 以上の Internet Explorer 6 のバグ...