You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MariaDB是否存在类似PostgreSQL的transaction_timestamp()事务起始时间函数

问题内容

我在调研时态查询时发现,MariaDB的时态查询实现属于表现较好的方案,但我按照官方文档步骤操作时遇到了问题。
研究过程中我发现MariaDB缺少PostgreSQL提供的transaction_timestamp()函数,PostgreSQL相关时间函数说明如下:

PostgreSQL还提供了返回当前语句起始时间、函数调用瞬间实际时间的函数,完整非SQL标准时间函数列表为:

transaction_timestamp()
statement_timestamp()
clock_timestamp()
timeofday()
now()

我执行了如下操作(步骤参考官方文档):

create table t 
(
   x int, test timestamp(6),
   start_tid bigint unsigned generated always as row start invisible,
   end_tid   bigint unsigned generated always as row end   invisible,
   period for system_time(start_tid, end_tid)
) with system versioning;

随后运行以下语句:

start transaction;
insert into t (x, test) values (1, now()), (2, now()), (3, now());
select sleep (5);  -- 模拟一个运行时间很长的报表查询
insert into t (x, test) values (11, now()), (12, now()), (13, now());
commit work;

之后执行查询:

select  
  x, test, start_tid, end_tid
from t;

得到如下结果:

x   test                start_tid   end_tid
1   2021-11-07 11:43:25 60612       18446744073709551615
2   2021-11-07 11:43:25 60612       18446744073709551615
3   2021-11-07 11:43:25 60612       18446744073709551615

-- 注意此处存在5秒间隔!

11  2021-11-07 11:43:30 60612       18446744073709551615
12  2021-11-07 11:43:30 60612       18446744073709551615
13  2021-11-07 11:43:30 60612       18446744073709551615

我可以获取到两次insert操作各自的执行时间,但无法在MariaDB中获取整个事务的统一起始时间。
在PostgreSQL中执行几乎相同的操作得到结果如下:

x       tx_time                         clock_time
1   2021-11-07 12:01:05.574651  2021-11-07 12:01:05.575062
2   2021-11-07 12:01:05.574651  2021-11-07 12:01:05.575145
3   2021-11-07 12:01:05.574651  2021-11-07 12:01:05.57515

-- 此处tx_time保持不变,clock_time符合预期产生了5秒偏移

11  2021-11-07 12:01:05.574651  2021-11-07 12:01:10.577289
12  2021-11-07 12:01:05.574651  2021-11-07 12:01:10.577307
13  2021-11-07 12:01:05.574651  2021-11-07 12:01:10.577324 

我了解到可以通过关联mysql.transaction_registry表实现该需求,但希望能直接通过SQL内置功能实现,请问是否有对应解决方案?


解决方案

方案1:手动捕获事务起始时间(推荐,零额外依赖)

MariaDB目前没有内置和PostgreSQL transaction_timestamp() 完全等价的原生函数,最低成本的替代方案是在事务启动时一次性捕获时间存入用户变量,后续所有操作复用该变量即可:

start transaction;
-- 事务开始时仅捕获一次时间,全事务生命周期内复用
set @transaction_start = now(6);
insert into t (x, test) values (1, @transaction_start), (2, @transaction_start), (3, @transaction_start);
select sleep(5);
insert into t (x, test) values (11, @transaction_start), (12, @transaction_start), (13, @transaction_start);
commit;

该方案返回的test字段值完全和PostgreSQL的transaction_timestamp()效果一致,无需修改数据库配置、也无需关联系统表。

方案2:调整时间函数行为适配需求

MariaDB的now()默认返回语句执行起始时间,你可以通过调整会话参数修改时间返回逻辑:

  1. 若需要和PostgreSQL的statement_timestamp()等价的效果,直接使用原生now()即可,无需额外修改
  2. 若需要和clock_timestamp()等价的效果(返回函数执行瞬间的实时时间),可以使用sysdate(6)函数

补充说明

你观察到的同一事务内所有行start_tid相同是预期设计:start_tid是事务提交时分配的全局唯一事务ID,同一个事务内写入的所有行都会共用同一个ID值。如果不想手动维护用户变量,只能关联mysql.transaction_registry系统表,通过start_tid匹配对应的事务起始时间,该表查询性能足够支撑常规业务场景。


内容的提问来源于stack exchange,提问作者SQL_Padawan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 07:24:03