{"@timestamp":"2023-02-28T17:16:29.234+08:00","@version":"0.0.1","message":"开始执行sql","logger_name":"com.redick.support.mysql.Mysql5StatementInterceptor","thread_name":"http-nio-3321-exec-4","level":"INFO","level_value":20000,"traceId":"9ed930dc-4cc6-4719-bf33-9fcb618fd65b","spanId":"1","request_type":"getName","parentId":"0","trace_tag":"sql_exec_before"}
Java は MySQL ドライバー インターセプターをどのように使用して、時間のかかる SQL 計算を実装しますか?
背景
会社の要件の 1 つは、会社の既存のリンク トラッキング ログ コンポーネントが MySQL の SQL 実行時間の出力をサポートしている必要があるということです。リンク トラッキングを実装する一般的な方法は、サードパーティのフレームワークまたはツールを実装することです。 MySQL のインターセプター インターフェイスやフィルター インターフェイスも例外ではなく、実際には、MySQL によって駆動されるインターセプター インターフェイスを実装しているだけです。
具体的な実装
MySQL チャネルにはさまざまなバージョンがあり、さまざまなバージョンのインターセプター インターフェイスも異なるため、使用している MySQL ドライバーのさまざまなバージョンに応じて応答インターセプターを実装する必要があります。 . , 次に、MySQL チャネル 5、6、8 の実装方法をそれぞれ紹介します。
MySQL5
ここでは、StatementInterceptorV2
インターフェイスを実装するための例として MySQL チャネル 5.1.18 を取り上げます。主な実装ロジックは preProcess## にあります。 # と
postProcess メソッド、これら 2 つのメソッドは SQL 実行の前後に実行されるメソッドです。私が使用するフレームワークは logback です。ここでは MDC を使用して、SQL 実行前のタイムスタンプを記録します。コードは # にあります。 ##postProcess
メソッド。MDC.put("sql_exec_time", start);
、ThreadLocal などを使用して実装し、MDC.get("sql_exec_time" を使用することもできます) ") の
postProcess メソッド
SQL 実行前の記録時間を取り出し、最後に現在のタイムスタンプから SQL 実行前の時間を減算して SQL 実行時間を計算します。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>import static net.logstash.logback.marker.Markers.append;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.ResultSetInternalMethods;
import com.mysql.jdbc.Statement;
import com.mysql.jdbc.StatementInterceptorV2;
import com.redick.util.LogUtil;
import java.sql.SQLException;
import java.util.Properties;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
/**
* @author Redick01
*/
@Slf4j
public class Mysql5StatementInterceptor implements StatementInterceptorV2 {
@Override
public void init(Connection connection, Properties properties) throws SQLException {
}
@Override
public ResultSetInternalMethods preProcess(String s, Statement statement, Connection connection)
throws SQLException {
String start = String.valueOf(System.currentTimeMillis());
MDC.put("sql_exec_time", start);
log.info(LogUtil.customizeMarker(LogUtil.kLOG_KEY_TRACE_TAG, "sql_exec_before"), "开始执行sql");
return null;
}
@Override
public boolean executeTopLevelOnly() {
return false;
}
@Override
public void destroy() {
}
@Override
public ResultSetInternalMethods postProcess(String s, Statement statement,
ResultSetInternalMethods resultSetInternalMethods, Connection connection, int i,
boolean b, boolean b1, SQLException e) throws SQLException {
long start = Long.parseLong(MDC.get("sql_exec_time"));
long end = System.currentTimeMillis();
log.info(LogUtil.customizeMarker(LogUtil.kLOG_KEY_TRACE_TAG, "sql_exec_after")
.and(append(LogUtil.kLOG_KEY_SQL_EXEC_DURATION, end - start)), "结束执行sql");
return null;
}
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
MySQL6
MySQL6 と MySQL5 は基本的に同じですが、インターフェイスは同じではありません。コードを直接記述するだけです。
import static net.logstash.logback.marker.Markers.append; import com.mysql.cj.api.MysqlConnection; import com.mysql.cj.api.jdbc.Statement; import com.mysql.cj.api.jdbc.interceptors.StatementInterceptor; import com.mysql.cj.api.log.Log; import com.mysql.cj.api.mysqla.result.Resultset; import com.redick.util.LogUtil; import java.sql.SQLException; import java.util.Properties; import lombok.extern.slf4j.Slf4j; import org.slf4j.MDC; /** * @author Redick01 */ @Slf4j public class Mysql6StatementInterceptor implements StatementInterceptor { @Override public StatementInterceptor init(MysqlConnection mysqlConnection, Properties properties, Log log) { return null; } @Override public <T extends Resultset> T preProcess(String s, Statement statement) throws SQLException { String start = String.valueOf(System.currentTimeMillis()); MDC.put("sql_exec_time", start); log.info(LogUtil.customizeMarker(LogUtil.kLOG_KEY_TRACE_TAG, "sql_exec_before"), "开始执行sql"); return null; } @Override public boolean executeTopLevelOnly() { return false; } @Override public void destroy() { } @Override public <T extends Resultset> T postProcess(String s, Statement statement, T t, int i, boolean b, boolean b1, Exception e) throws SQLException { long start = Long.parseLong(MDC.get("sql_exec_time")); long end = System.currentTimeMillis(); log.info(LogUtil.customizeMarker(LogUtil.kLOG_KEY_TRACE_TAG, "sql_exec_after") .and(append(LogUtil.kLOG_KEY_SQL_EXEC_DURATION, end - start)), "结束执行sql"); return null; } }
MySQL8
Interception MySQL8 と MySQL5/6 のインターセプタ インターフェイスがまた異なります。MySQL8 のインターセプタ インターフェイスは
com.mysql.cj.interceptors.QueryInterceptor です。SQL 実行時間のカウント方法は同じです。コードは次のとおりです。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>import static net.logstash.logback.marker.Markers.append;
import com.mysql.cj.MysqlConnection;
import com.mysql.cj.Query;
import com.mysql.cj.interceptors.QueryInterceptor;
import com.mysql.cj.log.Log;
import com.mysql.cj.protocol.Resultset;
import com.mysql.cj.protocol.ServerSession;
import com.redick.util.LogUtil;
import java.util.Properties;
import java.util.function.Supplier;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
/**
* @author Redick01
*/
@Slf4j
public class Mysql8QueryInterceptor implements QueryInterceptor {
@Override
public QueryInterceptor init(MysqlConnection mysqlConnection, Properties properties, Log log) {
return null;
}
@Override
public <T extends Resultset> T preProcess(Supplier<String> supplier, Query query) {
String start = String.valueOf(System.currentTimeMillis());
MDC.put("sql_exec_time", start);
log.info(LogUtil.customizeMarker(LogUtil.kLOG_KEY_TRACE_TAG, "sql_exec_before"), "开始执行sql");
return null;
}
@Override
public boolean executeTopLevelOnly() {
return false;
}
@Override
public void destroy() {
}
@Override
public <T extends Resultset> T postProcess(Supplier<String> supplier, Query query, T t,
ServerSession serverSession) {
long start = Long.parseLong(MDC.get("sql_exec_time"));
long end = System.currentTimeMillis();
log.info(LogUtil.customizeMarker(LogUtil.kLOG_KEY_TRACE_TAG, "sql_exec_after")
.and(append(LogUtil.kLOG_KEY_SQL_EXEC_DURATION, end - start)), "结束执行sql");
return null;
}
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
Use Method
MySQL5 と 6 は同じ方法で使用されます。次の
statementInterceptors パラメータをデータベース リンクの URL に追加します。例: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'> url: jdbc:mysql://127.0.0.1:3316/log-helper?useUnicode=true&characterEncoding=UTF8&statementInterceptors=com.redick.support.mysql.Mysql5StatementInterceptor&serverTimezone=CST</pre><div class="contentsignin">ログイン後にコピー</div></div>
MySQL8 は URL に ## を追加します。#queryInterceptors
url: jdbc:mysql://127.0.0.1:3316/log-helper?useUnicode=true&characterEncoding=UTF8&queryInterceptors=com.redick.support.mysql.Mysql8QueryInterceptor&serverTimezone=CST
テスト結果
SQL 実行前ログ{"@timestamp":"2023-02-28T17:16:29.234+08:00","@version":"0.0.1","message":"开始执行sql","logger_name":"com.redick.support.mysql.Mysql5StatementInterceptor","thread_name":"http-nio-3321-exec-4","level":"INFO","level_value":20000,"traceId":"9ed930dc-4cc6-4719-bf33-9fcb618fd65b","spanId":"1","request_type":"getName","parentId":"0","trace_tag":"sql_exec_before"}
ログイン後にコピー#) ##SQL 実行後ログ、SQL_duration の識別には SQL の実行に 3 ミリ秒かかります
{"@timestamp":"2023-02-28T17:16:29.234+08:00","@version":"0.0.1","message":"开始执行sql","logger_name":"com.redick.support.mysql.Mysql5StatementInterceptor","thread_name":"http-nio-3321-exec-4","level":"INFO","level_value":20000,"traceId":"9ed930dc-4cc6-4719-bf33-9fcb618fd65b","spanId":"1","request_type":"getName","parentId":"0","trace_tag":"sql_exec_before"}
{"@timestamp":"2023-02-28T17:16:29.237+08:00","@version":"0.0.1","message":"结束执行sql","logger_name":"com.redick.support.mysql.Mysql5StatementInterceptor","thread_name":"http-nio-3321-exec-4","level":"INFO","level_value":20000,"traceId":"9ed930dc-4cc6-4719-bf33-9fcb618fd65b","spanId":"1","request_type":"getName","parentId":"0","trace_tag":"sql_exec_after","sql_duration":3}
以上がJava は MySQL ドライバー インターセプターをどのように使用して、時間のかかる SQL 計算を実装しますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









PHP and Python each have their own advantages, and the choice should be based on project requirements. 1.PHPは、シンプルな構文と高い実行効率を備えたWeb開発に適しています。 2。Pythonは、簡潔な構文とリッチライブラリを備えたデータサイエンスと機械学習に適しています。

NAVICATプレミアムを使用してデータベースを作成します。データベースサーバーに接続し、接続パラメーターを入力します。サーバーを右クリックして、[データベースの作成]を選択します。新しいデータベースの名前と指定された文字セットと照合を入力します。新しいデータベースに接続し、オブジェクトブラウザにテーブルを作成します。テーブルを右クリックして、データを挿入してデータを挿入します。

MySQLは、オープンソースのリレーショナルデータベース管理システムです。 1)データベースとテーブルの作成:createdatabaseおよびcreateTableコマンドを使用します。 2)基本操作:挿入、更新、削除、選択。 3)高度な操作:参加、サブクエリ、トランザクション処理。 4)デバッグスキル:構文、データ型、およびアクセス許可を確認します。 5)最適化の提案:インデックスを使用し、選択*を避け、トランザクションを使用します。

MySQLとSQLは、開発者にとって不可欠なスキルです。 1.MYSQLはオープンソースのリレーショナルデータベース管理システムであり、SQLはデータベースの管理と操作に使用される標準言語です。 2.MYSQLは、効率的なデータストレージと検索機能を介して複数のストレージエンジンをサポートし、SQLは簡単なステートメントを通じて複雑なデータ操作を完了します。 3.使用の例には、条件によるフィルタリングやソートなどの基本的なクエリと高度なクエリが含まれます。 4.一般的なエラーには、SQLステートメントをチェックして説明コマンドを使用することで最適化できる構文エラーとパフォーマンスの問題が含まれます。 5.パフォーマンス最適化手法には、インデックスの使用、フルテーブルスキャンの回避、参加操作の最適化、コードの読み取り可能性の向上が含まれます。

手順に従って、NAVICATで新しいMySQL接続を作成できます。アプリケーションを開き、新しい接続(CTRL N)を選択します。接続タイプとして「mysql」を選択します。ホスト名/IPアドレス、ポート、ユーザー名、およびパスワードを入力します。 (オプション)Advanced Optionsを構成します。接続を保存して、接続名を入力します。

次の手順でphpmyadminを開くことができます。1。ウェブサイトコントロールパネルにログインします。 2。phpmyadminアイコンを見つけてクリックします。 3。MySQL資格情報を入力します。 4.「ログイン」をクリックします。

データの専門家として、さまざまなソースから大量のデータを処理する必要があります。これは、データ管理と分析に課題をもたらす可能性があります。幸いなことに、AWS GlueとAmazon Athenaの2つのAWSサービスが役立ちます。

データベースから直接削除された行を直接回復することは、バックアップまたはトランザクションロールバックメカニズムがない限り、通常不可能です。キーポイント:トランザクションロールバック:トランザクションがデータの回復にコミットする前にロールバックを実行します。バックアップ:データベースの定期的なバックアップを使用して、データをすばやく復元できます。データベーススナップショット:データベースの読み取り専用コピーを作成し、データが誤って削除された後にデータを復元できます。削除ステートメントを使用して注意してください:誤って削除されないように条件を慎重に確認してください。 WHERE句を使用します:削除するデータを明示的に指定します。テスト環境を使用:削除操作を実行する前にテストします。
