会社の要件の 1 つは、会社の既存のリンク トラッキング ログ コンポーネントが MySQL の SQL 実行時間の出力をサポートしている必要があるということです。リンク トラッキングを実装する一般的な方法は、サードパーティのフレームワークまたはツールを実装することです。 MySQL のインターセプター インターフェイスやフィルター インターフェイスも例外ではなく、実際には、MySQL によって駆動されるインターセプター インターフェイスを実装しているだけです。
MySQL チャネルにはさまざまなバージョンがあり、さまざまなバージョンのインターセプター インターフェイスも異なるため、使用している MySQL ドライバーのさまざまなバージョンに応じて応答インターセプターを実装する必要があります。 . , 次に、MySQL チャネル 5、6、8 の実装方法をそれぞれ紹介します。
ここでは、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 実行時間を計算します。 <pre class="brush:java;">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>
MySQL6
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
です。SQL 実行時間のカウント方法は同じです。コードは次のとおりです。 <pre class="brush:java;">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>
Use Method
パラメータをデータベース リンクの URL に追加します。例: <pre class="brush:yaml;"> url: jdbc:mysql://127.0.0.1:3316/log-helper?useUnicode=true&characterEncoding=UTF8&statementInterceptors=com.redick.support.mysql.Mysql5StatementInterceptor&serverTimezone=CST</pre>
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.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 サイトの他の関連記事を参照してください。