AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 208363
Accepted
Gajus
Gajus
Asked: 2018-06-01 04:58:35 +0800 CST2018-06-01 04:58:35 +0800 CST 2018-06-01 04:58:35 +0800 CST

如何检查当前连接是否在事务中?

  • 772

我需要我的程序代码来确保在事务中执行某些逻辑部分。

什么查询会告诉我当前的交易 ID/其他信息,这些信息可以让我确定我是否在交易中进行交易?

BEGIN;
-- How to check if I am in a transaction?
COMMIT;
postgresql transaction
  • 3 3 个回答
  • 2045 Views

3 个回答

  • Voted
  1. Best Answer
    Gajus
    2018-06-01T05:48:48+08:002018-06-01T05:48:48+08:00

    一个简单的方法是比较now()。statement_timestamp()

    • now()给出当前日期和时间(当前事务的开始)。
    • statement_timestamp()给出当前日期和时间(当前语句的开始)。

    例子:

    SELECT now() = statement_timestamp();
    -- TRUE
    
    BEGIN;
    SELECT now() = statement_timestamp();
    -- FALSE
    

    另一种选择是执行两个查询:

    SELECT txid_current();
    SELECT txid_current();
    

    并比较生成的 xid。如果相同,那么您正在交易中。

    后一种方法的缺点是每次都会txid_current()增加 xid 值,并将进一步推动您进入wraparound。

    • 5
  2. BigSmoke
    2022-05-06T05:22:02+08:002022-05-06T05:22:02+08:00

    从 PostgreSQL 版本 10 及更高版本(即,截至 2022 年 5 月的所有支持版本),除了txid_current()@Gajus 已经提到的函数之外,还有一个txid_current_if_assigned()函数,它返回“如果尚未分配 [transaction] ID 则返回 NULL”允许您“避免不必要地消耗 XID”(这是@Gajus 在 2018 年的回答中暗示的问题)。

    事实上,从 PostgreSQL 13 开始,这些txid_带前缀的函数已被弃用,取而代之的是pg_current_xact_id()和pg_current_xact_id_if_assigned()。

    如果你只是想知道你当前是否在事务中,那么使用它比使用更好pg_current_xact_id_if_assigned()的pg_current_xact_id()原因是,根据经验,你想避免不必要的 XID 消耗。例如,GitLab遇到了问题,因为他们过于广泛地使用了保存点。

    但是,警告也适用于pg_current_xact_id_if_assigned(). NULL只要您的事务中没有写入任何内容,它就会返回,因为 PostgreSQL 在写入操作发生之前不会分配事务 ID。一种可能的解决方法是创建一个绑定事务的临时表:

    SELECT pg_current_xact_id_if_assigned() IS NOT NULL AS is_transaction;
    
     is_transaction
    ----------------
     f
    (1 row)
    
    BEGIN TRANSACTION;  -- Making it explicitly READ WRITE won't make a difference.
    
    SELECT pg_current_xact_id_if_assigned() IS NOT NULL AS is_transaction;
    
     is_transaction
    ----------------
     f
    (1 row)
    
    CREATE TEMPORARY TABLE a (b int) ON COMMIT DROP;
    
    SELECT pg_current_xact_id_if_assigned() IS NOT NULL AS is_transaction;
    
     is_transaction
    ----------------
     t
    (1 row)
    

    你有它。

    如果您在CREATE TEMPORARY TABLE … ON COMMIT DROP事务之外的何处运行语句,它将在每个变异语句(在自动提交模式下)执行的隐式事务结束时消失。

    编辑1:请注意,您不能将此逻辑包装到函数或过程中,因为函数/过程调用语句将包装在隐式事务中,因此您的am_i_inside_a_transaction()函数将始终返回TRUE。

    编辑2:我想明确表示,除了我的答案的信息价值之外,我仍然相信@Gajus 他自己的答案的比较时间戳方法优于该pg_current_xact_id_if_assigned()方法。transaction_timestamp()并且他的方法可以通过使用而不是更加明确now():

    CREATE FUNCTION in_transaction() RETURNS boolean
    LANGUAGE SQL
    RETURN transaction_timestamp() != statement_timestamp()
    ;
    
    SELECT in_transaction();
    
     in_transaction
    ----------------
     f
    (1 row)
    
    BEGIN;
    SELECT in_transaction();
    
     in_transaction
    ----------------
     t
    (1 row)
    

    不过,这里也有一个警告,因为statement_timestamp()“从客户端收到最新命令消息的时间”。这意味着如果您要将上述函数调用嵌套在另一个函数中,该函数将始终返回FALSE。

    • 3
  3. Holger Jakobs
    2021-05-08T03:36:58+08:002021-05-08T03:36:58+08:00

    有趣的是,psql 和在应用程序中执行相同的语句会产生不同的结果。我尝试了 Tcl 脚本和 DBeaver。

    陈述:SELECT now(), statement_timestamp();

    psql:2021-05-07 13:31:10.135851+02 | 2021-05-07 13:31:10.135851+02

    DBeaver:2021-05-07 13:31:00.633784+02|2021-05-07 13:31:00.633913+02

    Tcl 脚本:{now {2021-05-07 13:24:54.659837+02} statement_timestamp {2021-05-07 13:24:54.65985+02}}

    因此,在 psql now() 和 statement_timestamp() 中,当不在事务中时是相同的,而在其他情况下,这两个值略有不同,大约 100 微秒。

    • 0

相关问题

  • 我可以在使用数据库后激活 PITR 吗?

  • 运行时间偏移延迟复制的最佳实践

  • 存储过程可以防止 SQL 注入吗?

  • PostgreSQL 中 UniProt 的生物序列

  • PostgreSQL 9.0 Replication 和 Slony-I 有什么区别?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve