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

PostgreSQL中READ COMMITTED级别的只读事务异常是什么及如何复现?

只读事务异常(read-only transaction anomaly)解析与复现

1. 什么是只读事务异常?

只读事务异常指的是:一个只读事务在执行过程中,多次读取到的数据组合,无法对应数据库在任何一个时间点的一致状态。

简单来说,这个只读事务看到的不是数据库某一时刻的完整快照,而是不同时间点数据的“拼接”——比如先读取了表A的旧状态,之后又读取了表B被其他事务修改后的新状态,这两组数据放在一起,在数据库的历史中从未同时存在过,违背了“读取一致性”的直觉。

2. PostgreSQL READ COMMITTED级别下的复现步骤

前置准备

先创建测试表并插入初始数据:

CREATE TABLE accounts (id INT PRIMARY KEY, balance INT);
INSERT INTO accounts VALUES (1, 100), (2, 100);

复现操作(需要3个独立的SQL会话/窗口)

  • 会话1(只读事务):

    -- 启动READ COMMITTED级别的事务
    BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;
    -- 第一次读取:获取账户1的余额
    SELECT balance FROM accounts WHERE id = 1;
    -- 此时返回结果为100
    
  • 会话2(修改事务):

    BEGIN;
    -- 执行转账操作:从账户1转50到账户2
    UPDATE accounts SET balance = balance - 50 WHERE id = 1;
    UPDATE accounts SET balance = balance + 50 WHERE id = 2;
    -- 提交事务,让修改生效
    COMMIT;
    
  • 回到会话1:

    -- 第二次读取:获取账户2的余额
    SELECT balance FROM accounts WHERE id = 2;
    -- 此时返回结果为150
    

异常验证

会话1的只读事务先后得到了账户1=100和账户2=150的结果,但数据库从未存在过这样的状态:

  • 转账前状态:(100, 100)
  • 转账后状态:(50, 150)

这两组数据的组合完全不符合任何时间点的一致性,也就触发了只读事务异常。

内容的提问来源于stack exchange,提问作者Super Kai - Kazuya Ito

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 23:45:41