为此,我在 Google 上四处寻找,但找不到任何相关内容。基本上,我想掌握长期运行的交易。
现在,我通过 information_schema.INNODB_TRX
或查看 show engine innodb status
的输出来找到 trx_id
和然后打开 general_logs
以查看所有查询正在运行的内容。
有没有办法,我可以使用 jdbc
或 hibernate
在我的代码中获取此 transaction_id
以便我可以登录我的服务器日志?
最佳答案
甲骨文
使用 Oracle 时,必须执行以下 SQL 查询:
SELECT RAWTOHEX(tx.xid)
FROM v$transaction tx
JOIN v$session s ON tx.ses_addr = s.saddr
v$transaction
View 提供有关当前正在运行的数据库事务的信息。但是,我们的系统中可以运行多个事务,这就是我们将 v$transaction
与 v$session
View 结合在一起的原因。
v$session
View 提供有关我们当前 session 或数据库连接的信息。通过匹配v$transaction
和v$session
View 之间的 session 地址,我们可以找到xid
列给出的当前正在运行的事务标识符在 v$transaction
View 中。
因为 xid
列是 RAW
类型,我们使用 RAWTOHEX
将交易标识符二进制值转换为其十六进制表示。
Oracle assigns a transaction identifier only if it needs to assign an undo segment, which implies that an INSERT, UPDATE or DELETE DML statement has been executed.
So, read-only transactions will not have a transaction identifier assigned.
SQL 服务器
使用 SQL Server 时,您只需执行以下 SQL 查询:
SELECT CONVERT(VARCHAR, CURRENT_TRANSACTION_ID())
因为 CURRENT_TRANSACTION_ID
函数返回一个 BIGINT
列值,我们使用 CONVERT
来获取它的字符串表示形式。
PostgreSQL
使用PostgreSQL Server时,可以执行如下SQL查询获取当前事务id:
SELECT CAST(txid_current() AS text)
因为 txid_current
函数返回一个 BIGINT
列值,我们使用 CAST
来获取它的字符串表示形式。
MySQL 和 MariaDB
当使用 MySQL 或 MariaDB 时,您可以执行以下 SQL 查询来获取当前事务 ID:
SELECT tx.trx_id
FROM information_schema.innodb_trx tx
WHERE tx.trx_mysql_thread_id = connection_id()
information_schema
目录中的innodb_trx
View 提供有关当前正在运行的数据库事务的信息。由于我们的系统中可以运行多个事务,因此我们需要通过将 session 或数据库连接标识符与当前正在运行的 session 进行匹配来过滤事务行。
Just like it was the case with Oracle, since MySQL 5.6, only read-write transactions will get a transaction identifier.
Because assigning a transaction id has a given overhead, read-only transactions skip this process. For more details, check out this article.
This read-only transaction optimization works the same way in MariaDB, meaning that a transaction id is only assigned for read-write transactions only.
数据库
使用HyperSQL数据库时,可以执行如下SQL查询获取当前交易id:
VALUES (TRANSACTION_ID())
使用 MDC 记录事务 ID
事务 ID 对于日志记录很有用,因为它允许我们汇总在给定数据库事务的上下文中执行的所有操作。
假设我们已经将上面的 SQL 查询封装在 transactionId
中方法,我们可以提取当前事务 ID 并将其作为 MDC 变量传递给 Logger 框架。
因此,对于 SLF4J,您可以使用 put
方法,如下例所示:
MDC.put("txId", String.format(" TxId: [%s]", transactionId(entityManager)));
MDC (Mapped Diagnostic Context)用于记录 ThreadLocal
对 Java 线程的作用。基本上,MDC 允许您注册键/值对,这些键/值对仅限于当前运行的线程,您可以在日志记录框架构建日志消息时引用它们。
要将“txId”日志变量打印到日志中,我们需要在日志附加程序模式中包含此变量:
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>TRACE</level>
</filter>
<encoder>
<Pattern>%-5p [%t]:%X{txId} %c{1} - %m%n</Pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
%X{txId}
模式用于引用 txId
日志变量。
关于java - 如何使用 JDBC 或 Hibernate 获取当前数据库事务 ID?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29894573/