如何获取当前数据库事务ID - Vlad Mihalcea


在本文中,我将向您展示如何获取当前数据库事务ID。事务ID对于日志记录非常有用,尤其是如果要关联在同一数据库事务的上下文中执行的多个日志条目。

事务基础
在关系数据库中,事务是必需的。即使您没有声明数据库事务,您仍然会被默认使用了一个事务。
您可自己配置的唯一事务是事务范围作用域。因此,如果您未明确声明事务边界,则每个SQL语句将在其自己的数据库事务中执行,这意味着您将使用自动提交模式。
但是,大多数情况下,业务用例需要执行多个SQL语句,在这种情况下,自动提交模式将阻止数据库能够回滚在当前运行的业务用例的上下文中执行的所有语句。
因此,服务层方法使用注释进行@Transactional注释。在执行@Transactional方法时,在当前业务用例的上下文中执行的所有SQL语句将共享相同的数据库事务。

获取事务ID
您可以使用特定于数据库的SQL查询从数据库中获取数据库事务标识符。
Oracle
使用Oracle时,必须执行以下SQL查询:

SELECT RAWTOHEX(tx.xid)
FROM v$transaction tx
JOIN v$session s ON tx.ses_addr = s.saddr

v$transaction视图提供有关当前运行的数据库事务的信息。但是,可以在我们的系统中运行的多笔交易事务时,这就是为什么我们加入v$transaction与v$session视图。

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

xid列是类型RAW,我们RAWTOHEX用于将事务标识符二进制值转换为其十六进制表示。

Oracle仅在需要分配撤消段时才分配事务标识符,这意味着已执行INSERT,UPDATE或DELETE DML语句。
因此,只读事务不会分配事务标识符。有关撤消日志的更多详细信息,请查看此文章

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

SELECT CONVERT(VARCHAR, CURRENT_TRANSACTION_ID())

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

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

SELECT CAST(txid_current() AS text)

因为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()

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

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

由于分配事务标识具有给定的开销,因此只读事务会跳过此过程。有关更多详细信息,请查看此文章。

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

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

VALUES (TRANSACTION_ID())