PostgreSQL:查明当前事务是否创建了一行

时间:2017-07-07 07:07:05

标签: sql postgresql transactions commit

是否有可能找出当前事务是否已创建表中的行(因此当前事务仍处于活动状态时,因此尚未显示其他事务)?

我的用例:我正在向数据库添加事件记录。这是在plpgsql触发器中完成的。事件表中的一行如下所示:(event id:serial, event action:text, count:integer:default 1)

现在,我的问题背后的原因:如果此事务已创建某个行(很可能是在另一个触发器中),我可以增加计数而不是在事件表中创建新行。

2 个答案:

答案 0 :(得分:1)

你可能会考虑这样的事情:

create table ConnectionCurrentAction (
     connectionID int primary key,
     currentActionID uuid
)

然后在交易开始时:

delete ConnectionCurrentAction where connectionID = pg_backend_pid()
insert ConnectionCurrentAction(connectionID, currentActionID) 
select pg_backend_pid(), uuid_generate_v4()

您可以将其包含在名为say audit_action_begin

的过程中

注意:您可以选择强制执行"操作"通过删除删除来明确创建。

在交易结束时,请audit_action_end

delete ConnectionCurrentAction where connectionID = pg_backend_pid()

每当您想知道当前的交易时:

(select currentActionID from ConnectionCurrentAction where connectionID - pg_backend_pid()(

您可以将其包含在函数audit_action_current()

然后,您可以将currentActionID放入日志中,这样您就可以识别当前操作中是否创建了行。这还允许您识别在当前逻辑操作中创建不同审计表中的行的位置。

如果你不想使用uuid,那么序列就可以了。我喜欢uuids。

答案 1 :(得分:1)

你可以只查找这样的记录条目:

SELECT ...
FROM tablename
WHERE xmin = current_txid() % (2^32)::bigint;

这将在当前事务中找到所有添加或修改的行。

缺点是这将强制对整个表进行顺序扫描,因为您无法在系统列上建立索引,所以无法避免这种情况。

因此,每当插入或更新行时,您都可以向表中添加额外的列xid,该列填充txid_current()::bigint。这样的列可以被索引并有效地用于搜索:

SELECT ...
FROM tablename
WHERE xid = current_txid();