データベースクエリタイムアウト最適化問題の実践記録
問題の発見
7月に入ってから、いくつかの定型タスクがエラーを報告しているのをよく見かけ、例外の原因を調べた結果、おそらくデータベース実行例外を突き止めました。
### Error querying database. cause: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Unsupported command
### The error may exist in class path resource [mapper/XXXXXXXXX-Mapper.xml]
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: select t3.cino, t2.sn as orderSn, t2.provider_id as providerId, t4.logistics_no as logisticsSn, t2.`name`,
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Unsupported command
MySQLNonTransientConnectionException: Unsupported command; Unsupported command; nested exception is com.mysql.jdbc.exceptions.jdbc4.
DataAccessResourceFailureException:
### Error querying database. cause: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Unsupported command
### The error may exist in class path resource [mapper/XXXXXXXXXOMapper.xml]
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: select t3.cino, t2.sn as orderSn, t2.provider_id as providerId, t4.logistics_no as logisticsSn,
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Unsupported command
原因を探る
1 DBAと一緒にmycat(会社はmycatを使用しています)とmysqlのエラーログを確認します。アプリケーションサービスがMyCatにKILL QUERYコマンドを送信しているが、myCatはKILL QUERYコマンドをサポートしていないことが判明した。このため、アプリケーション・サービスはUnsupported command exception errorを返します。
2021-07-02 10:46:33.567 WARN [$_NIOREACTOR-37-RW] (io.mycat.server.ServerQueryHandler.query(ServerQueryHandler.java:96)) - Unsupported command:KILL QUERY 2956587
2 記事内でKILLQUERYが発生するシナリオをググってみる
JDBCのタイムアウト機構を徹底分析
私は問題を見つけた、SQL実行タイムアウト、jdbcはmysqlサービスにkillコマンドを送信し、mysqlはSQLの実行を停止するようにします。しかし、それはコマンドを処理せず、直接エラーが返されたmycatサービスに渡されました。
3 アプリケーションサービスの構成を確認すると、jdbc:url構成のmysqlソケット実行タイムアウトは15s、mybatisスタンドアロンSQL実行文構成は20sと長い(ここの構成は注釈付きxmlであることに注意)。
3.1 mybatis xmlのsql文はクライアント側だけで実行され、テストしたsql実行時間は6、7秒程度で、15秒の制限を超えていません。しかし、タスクスケジューリングのタイムドログから、各タスクは全体で8秒程度実行されており、15秒以内にタイムアウトKILLコマンドを受信したmycatはsql実行に失敗していることになります。
4 タイムアウトをどこかに設定するか考える。mybatisの設定を見ると、default-statement-timeout = 5 という一律のsqlタイムアウトの設定がある。
-
mybatis のソースドキュメントを見ると、別途設定した mybatis @Options のタイムアウトプロパティが、yml で設定した default-statement-timeout プロパティを上書きしているようです。もしかして、@Optionsが効いていないのでしょうか?
5 そこで、ローカルでデバッグしてみることにしました。jdbcのqueryTimeoutはymlのmybatisのグローバル設定の値を取るので、@Optionsは本当に機能しないことがわかった。
問題を解決する
上記のように、sqlのstatmentはmybatisアノテーションとxmlを混在して使用しています。mybatisアノテーションとxmlの使い方に互換性がないためだと思われます。そこで、xmlのstatmentのタイムアウトの設定を変えてみました。設定は以下のように有効になりました。
また、@Optionsの設定も有効にすることができます。mybatisの@Optionsとxmlの設定は同時に有効にすることができないので、もしかしたらmybatisの他のアノテーションとxmlの設定は同時に有効にすることができないので、今後、読者がこの落とし穴を回避できるようになればいいと思います
おまけ:トランザクションタイムアウト、ステートメントタイムアウト、ソケットタイムアウトの違いについて
上記のmybatisで設定されているタイムアウトは、実はStatement Timeoutです。また、jdbc:urlで設定されているsocketTimeoutや、springで定義されているtransaction timeoutも存在します。トランザクションタイムアウト
で、この3つはどのように関係しているのでしょうか?
ステートメントタイムアウト
- ステートメントタイムアウトは、ステートメント文の実行時間を制限するために使用されます。これは、JDBCのjava.sql.Statement.setQueryTimeout(int timeout)を呼び出して設定できますが、通常はORMフレームワークを介して設定されます。
-
myBatisでは、ステートメントタイムアウトのデフォルト値は、defaultStatementTimeoutプロパティによって設定されます。また、xml の select, insert, update タグに timeout 属性を設定し、異なる sql ステートメントのタイムアウトを設定することもできます。
トランザクションタイムアウト
- Springが提供するトランザクションタイムアウトの設定も非常にシンプルで、各トランザクションの開始時刻と消費時刻を記録し、タイムアウト値を超えると例外をスローします。
-
トランザクションに3つのステートメントが含まれ、それぞれの実行に100ms、残りのビジネスロジックに50msかかるとすると、トランザクションのタイムアウトは少なくとも350ms(100 * 3 + 50)に設定する必要があります。
ソケットタイムアウト
-
JDBCのソケットタイムアウトは、データベースが突然停止したときやネットワークエラーが発生したときに重要です。TCP/IP の構造上、ソケットにはネットワーク・エラーを検出する方法がないため、アプリケーションはデータベース接続が停止したことを積極的に検出することができません。ソケットタイムアウトを設定しない場合、アプリケーションはデータベースが結果を返すまで無限に待つことになり、この接続はデッドコネクション(dead connection)と呼ばれます。
優先順位
- ソケットタイムアウトはトランザクションタイムアウトより、トランザクションタイムアウトはステートメントタイムアウトより優れており、ステートメントタイムアウトがトランザクションタイムアウトまたはソケットタイムアウトより大きい場合、その効果は発揮されないことを意味する
- ソケットタイムアウトを使用してステートメントの長さを制限することは推奨されないため、ソケットタイムアウトはステートメントタイムアウトよりも高くなければならず、さもなければソケットタイムアウトが先に有効になり、ステートメントタイムアウトは意味をなさなくなります。
概要
データベースクエリのタイムアウトの最適化の問題については、この記事はここで紹介されて、より関連するデータベースクエリのタイムアウトの最適化の内容は、スクリプトの家の前の記事を検索してくださいまたは次の関連記事を閲覧し続けるあなたは、将来的にはよりスクリプトハウスをサポートしています願っています!この記事では、データベースクエリのタイムアウトの最適化の問題については、ここで紹介されています。
パラメータの記事
関連
-
DataGrip データエクスポート/インポート実装例
-
gaussDBデータベース共通操作コマンド詳細
-
Linuxシステム用Navicatアクティベーションチュートリアル
-
Hbaseカラムナーストレージ入門チュートリアル
-
SQLyogダウンロード、インストール超詳細チュートリアル(プロテスト永久保存版)
-
Navicat Premium 15データベース接続フラッシュバックの問題を解決する
-
どのようなデータベースのサブベースのサブテーブルは、どのような状況でサブベースのサブテーブルを使用する必要があります。
-
外部キーの関連付けを行う SQL 文の完全な例
-
Navicat Premiumを使用して、データベースのテーブル構造情報をExcelにエクスポートする方法
-
SQLインジェクションの例とその解決方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
MySQLとRedisがデータの一貫性を確保する方法について説明します。
-
DeepinV20 Mariadbのクイックインストールを詳しくご紹介します。
-
ナビカット15のインストールチュートリアルを超詳しく解説(一番信頼できるのはこれ)
-
JMeterデータベースクエリ操作手順詳細説明
-
5分でわかる!データベースのデッドロックのシナリオと解決策
-
データベースキャッシュの最終的な整合性に関する4つのオプション
-
CentOS 8.2上のCouchDB 3.3データベースを展開する方法
-
SQLリレーショナルモデルの知識まとめ
-
タイプインジェクションとコミットインジェクションのSQLインジェクションチュートリアル
-
SQLインジェクションについて詳しく話すいくつかの散在する知識のポイント