有没有办法通过 JDBC 启用 MySQL 通用查询日志记录?我通过搜索发现的最接近的东西是能够通过 JDBC 记录慢查询(http://dev.mysql.com/doc/refman/5.5/en/connector-j-reference-configuration-properties.html)。也许我应该这样做并将慢查询阈值设置为 0 毫秒?
我想以人类可读的格式记录通过 MySQL 的所有查询,并希望指定日志文件应写入的位置。我知道我的性能会受到影响,但我的应用程序只有一个用户,而且非常简单,如果性能受到明显影响,我会感到惊讶。无论如何我都想尝试一下看看。
我相信我的另一个选择是打开二进制日志记录并使用 mysqlbinlog 将二进制日志转换为人类可读的格式,但听起来通用查询日志将提供一种更简单的方法来获取我想要的内容。
您可以像这样在 JDBC URL 中启用日志记录:
jdbc:mysql://host/db?logger=com.mysql.jdbc.log.Log4JLogger&profileSQL=true
其他日志记录后端可用(CommonsLogger、Slf4jLogger、JDK14Logger)。我相信直接 Log4J 日志记录在某些时候由于许可问题而被放弃,因此它可能不适用于您的 JDBC 驱动程序版本。
当然,您的类路径中需要相关日志库的 JAR,以及一个配置文件 (log4j.properties)。我会首先将根级别设置为 TRACE 以查看发生的情况,并在看到正在记录的内容后按日志级别和类别收紧它。
进一步阅读:
HTH
将“logger”和“profileSQL”添加到 jdbc url:
&logger=com.mysql.jdbc.log.Slf4JLogger&profileSQL=true
然后你会得到下面的SQL语句:
2016-01-14 10:09:43 INFO MySQL - FETCH created: Thu Jan 14 10:09:43 CST 2016 duration: 1 connection: 19130945 statement: 999 resultset: 0
2016-01-14 10:09:43 INFO MySQL - QUERY created: Thu Jan 14 10:09:43 CST 2016 duration: 1 connection: 19130945 statement: 999 resultset: 0 message: SET sql_mode='NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES'
2016-01-14 10:09:43 INFO MySQL - FETCH created: Thu Jan 14 10:09:43 CST 2016 duration: 1 connection: 19130945 statement: 999 resultset: 0
2016-01-14 10:09:43 INFO MySQL - QUERY created: Thu Jan 14 10:09:43 CST 2016 duration: 2 connection: 19130945 statement: 13 resultset: 17 message: select 1
2016-01-14 10:09:43 INFO MySQL - FETCH created: Thu Jan 14 10:09:43 CST 2016 duration: 0 connection: 19130945 statement: 13 resultset: 17
2016-01-14 10:09:43 INFO MySQL - QUERY created: Thu Jan 14 10:09:43 CST 2016 duration: 1 connection: 19130945 statement: 15 resultset: 18 message: select @@session.tx_read_only
2016-01-14 10:09:43 INFO MySQL - FETCH created: Thu Jan 14 10:09:43 CST 2016 duration: 0 connection: 19130945 statement: 15 resultset: 18
2016-01-14 10:09:43 INFO MySQL - QUERY created: Thu Jan 14 10:09:43 CST 2016 duration: 2 connection: 19130945 statement: 14 resultset: 0 message: update sequence set seq=seq+incr where name='demo' and seq=4602
2016-01-14 10:09:43 INFO MySQL - FETCH created: Thu Jan 14 10:09:43 CST 2016 duration: 0 connection: 19130945 statement: 14 resultset: 0
默认记录器是:
com.mysql.jdbc.log.StandardLogger
Mysql jdbc 属性列表:https://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html
如果您使用 Hibernate,并通过它执行所有数据访问,您可以通过将属性
hibernate.show_sql
设置为 true 来打开日志记录。 不过,这将编写参数化语句(例如 SELECT foo.id FROM foo WHERE foo.bar = ?
)。 如果您需要参数值,或者不使用像 Hibernate 这样的工具,您可能需要让 MySQL 写入此日志。 请参阅 MySQL 文档中的一般查询日志。
FWIW,MySQL 二进制日志是达到不同目的的一种手段;它记录数据的更改,并用于增量备份和/或复制。
SELECT
语句不会记录在二进制日志中。
编辑: 我可以通过将以下两行添加到 my.cnf 中(在确认两个变量均未设置后)并重新启动 MySQL 来让 MySQL 写入常规日志:
general_log = 1
general_log_file=/tmp/mysql-general.log
我最终找到了解决方法。我通过 Java 在运行时使用以下 SQL 查询修改 MySQL 全局系统变量来启用 MySQL 常规查询日志记录。
SET GLOBAL log_output="FILE"
SET GLOBAL general_log_file="Path/File"
SET GLOBAL general_log='ON'
我建议在 General_log_file 路径中使用正斜杠。即使在 Windows 环境中,我也无法使用反斜杠。
我使用以下 SQL 查询在运行时禁用常规查询日志记录。
SET GLOBAL general_log='OFF'
对于 Spring Boot 的最新 MySQL 驱动程序版本,请添加到 JDBC 连接 URL:
spring.datasource.url: jdbc:mysql://localhost:49172/INTEGRATION_DB?logger=com.mysql.cj.log.Slf4JLogger&profileSQL=true
它将使用 Slf4J 记录器。如果没有这样的记录器,可以使用标准记录器:
logger=com.mysql.cj.log.StandardLogger
也可以使用自定义记录器,只需实现接口
com.mysql.cj.log.Log
并在连接 URL 中指定新的记录器即可。
将 MySQL 与 mysql-connector-java-8.0.13.jar 一起使用,我将
profileSQL=true
添加到我的 JDBC 连接 URL。例如:
jdbc:mysql://${HOST}:${PORT}/${SCHEMA}?autoReconnect=true&profileSQL=true
您还可以将
&logger=com.mysql.cj.log.StandardLogger
添加到 URL,但这不是必需的,因为它是文档中指示的默认值。
文档参考:
https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-configuration-properties.html
日志输出读起来很烦人,因为它包含一个堆栈跟踪,指示查询在代码中的确切运行位置。如果有人找到排除堆栈跟踪的方法,请告诉我。
如果您使用的是log4j,并且希望将SQL日志写入单独的日志文件sql.log,可以如下配置:
appender.connectorJdbc.name = ConnectorJdbcAppender
appender.connectorJdbc.type = RollingFile
appender.connectorJdbc.append = true
appender.connectorJdbc.fileName = /xxx/log/connectorJdbc.log
logger.connectorJdbc.name = MySQL
logger.connectorJdbc.level = INFO
logger.connectorJdbc.appenderRef.connectorJdbc.ref = ConnectorJdbcAppender
需要注意的是,这里的日志名称是MySQL。