使用jdbc / hibernate获取当前的数据库事务ID?

Sun*_*wal 5 java mysql hibernate transactions jdbc

我已经在Google上四处浏览,但找不到任何相关内容。基本上,我想掌握长期运行的事务。

现在,我浏览information_schema.INNODB_TRX或查看的输出show engine innodb status以查找trx_id,然后打开general_logs以查看所有查询正在运行的内容。

有没有办法,我可以transaction_id使用jdbc或在我的代码中掌握这一点,hibernate以便可以将其记录在服务器日志中?

Vla*_*cea 6

甲骨文

使用 Oracle 时,必须执行以下 SQL 查询:

SELECT RAWTOHEX(tx.xid)
FROM v$transaction tx
JOIN v$session s ON tx.ses_addr = s.saddr
Run Code Online (Sandbox Code Playgroud)

v$transaction视图提供有关当前运行的数据库事务的信息。但是,我们的系统中可能有多个事务在运行,这就是我们v$transactionv$session视图与视图结合的原因。

v$session视图提供有关我们当前会话或数据库连接的信息。通过匹配v$transactionv$session视图之间的会话地址,我们可以找到视图中xid列给出的当前正在运行的事务标识符v$transaction

由于该xid列的类型为RAW,我们使用RAWTOHEX将交易标识符二进制值转换为其十六进制表示。

Oracle 仅在需要分配撤消段时才分配事务标识符,这意味着已经执行了 INSERT、UPDATE 或 DELETE DML 语句。

因此,只读事务不会分配事务标识符。

数据库服务器

使用 SQL Server 时,您只需执行以下 SQL 查询:

SELECT CONVERT(VARCHAR, CURRENT_TRANSACTION_ID())
Run Code Online (Sandbox Code Playgroud)

因为该CURRENT_TRANSACTION_ID函数返回一个BIGINT列值,所以我们使用CONVERT来获取它的 String 表示。

PostgreSQL

使用 PostgreSQL Server 时,您可以执行以下 SQL 查询来获取当前事务 id:

SELECT CAST(txid_current() AS text)
Run Code Online (Sandbox Code Playgroud)

因为该txid_current函数返回一个BIGINT列值,所以我们使用CAST来获取它的 String 表示。

MySQL 和 MariaDB

在使用 MySQL 或 MariaDB 时,您可以执行以下 SQL 查询来获取当前事务 id:

SELECT tx.trx_id
FROM information_schema.innodb_trx tx
WHERE tx.trx_mysql_thread_id = connection_id()
Run Code Online (Sandbox Code Playgroud)

目录中的innodb_trx视图information_schema提供有关当前运行的数据库事务的信息。由于我们的系统中可以运行多个事务,我们需要通过将会话或数据库连接标识符与当前正在运行的会话进行匹配来过滤事务行。

就像 Oracle 的情况一样,从 MySQL 5.6 开始,只有读写事务才能获得事务标识符。

因为分配一个事务 id 有一个给定的开销,只读事务跳过这个过程。有关更多详细信息,请查看这篇文章

这种只读事务优化在 MariaDB 中的工作方式相同,这意味着事务 id 仅分配给读写事务。

数据库

使用 HyperSQL 数据库时,可以执行以下 SQL 查询来获取当前事务 id:

VALUES (TRANSACTION_ID())
Run Code Online (Sandbox Code Playgroud)

使用 MDC 记录事务 ID

事务 id 对记录很有用,因为它允许我们聚合在给定数据库事务的上下文中执行的所有操作。

假设我们已经将上面的 SQL 查询封装在一个transactionId方法中,我们可以提取当前事务 id 并将其作为 MDC 变量传递给 Logger 框架。

因此,对于 SLF4J,您可以使用put以下示例所示的方法:

MDC.put("txId", String.format(" TxId: [%s]", transactionId(entityManager)));
Run Code Online (Sandbox Code Playgroud)

MDC(映射诊断上下文)用于记录ThreadLocalJava 线程的内容。基本上,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>
Run Code Online (Sandbox Code Playgroud)

%X{txId}模式用于引用txId日志变量。