Oracle
使用 Oracle 时,必须执行以下 SQL 查询:
SELECT RAWTOHEX(tx.xid)
FROM v$transaction tx
JOIN v$session s ON tx.ses_addr = s.saddr
The v$transaction
视图提供有关当前正在运行的数据库事务的信息。但是,我们的系统中可以运行多个事务,这就是我们加入的原因v$transaction
与v$session
view.
The v$session
视图提供有关当前会话或数据库连接的信息。通过匹配之间的会话地址v$transaction
and v$session
视图中,我们可以找到当前正在运行的事务标识符xid
栏目中的v$transaction
view.
因为xid
列的类型RAW
,我们正在使用RAWTOHEX
将事务标识符二进制值转换为其十六进制表示形式。
Oracle 仅在需要分配撤消段时才分配事务标识符,这意味着已执行 INSERT、UPDATE 或 DELETE DML 语句。
因此,只读事务不会分配事务标识符。
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()
The innodb_trx
查看在information_schema
目录提供有关当前正在运行的数据库事务的信息。由于我们的系统中可能有多个事务正在运行,因此我们需要通过将会话或数据库连接标识符与当前正在运行的会话进行匹配来过滤事务行。
就像 Oracle 的情况一样,从 MySQL 5.6 开始,只有读写事务才会获得事务标识符。
由于分配事务 ID 具有给定的开销,因此只读事务会跳过此过程。欲了解更多详情,请查看本文.
这种只读事务优化在 MariaDB 中的工作方式相同,这意味着事务 ID 仅分配给读写事务。
HSQLDB
使用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(映射诊断上下文)用于记录什么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>
The %X{txId}
模式用于引用txId
日志变量。