Sql 选择是否可以使用读取提交隔离级别在一个事务中获得不同的结果?

Sql 选择是否可以使用读取提交隔离级别在一个事务中获得不同的结果?,sql,postgresql,transactions,Sql,Postgresql,Transactions,下面是关于读取提交隔离级别的完整段落: Read Committed是PostgreSQL中的默认隔离级别。当 事务使用此隔离级别,即SELECT查询(不带FOR) UPDATE/SHARE子句)只查看查询开始前提交的数据; 它从未看到未提交的数据或在提交过程中提交的更改 通过并发事务执行查询。实际上,一个SELECT查询 在查询开始时查看数据库的快照 跑但是,SELECT确实可以看到以前执行的更新的效果 在它自己的事务中,即使它们尚未提交。 还要注意,两个连续的SELECT命令可以看到不同的数

下面是关于读取提交隔离级别的完整段落:

Read Committed是PostgreSQL中的默认隔离级别。当 事务使用此隔离级别,即SELECT查询(不带FOR) UPDATE/SHARE子句)只查看查询开始前提交的数据; 它从未看到未提交的数据或在提交过程中提交的更改 通过并发事务执行查询。实际上,一个SELECT查询 在查询开始时查看数据库的快照 跑但是,SELECT确实可以看到以前执行的更新的效果 在它自己的事务中,即使它们尚未提交。 还要注意,两个连续的SELECT命令可以看到不同的数据, 即使它们在单个事务中,如果其他 事务在第一次选择开始之后和之前提交更改 第二次选择开始


所以基本上:

SELECT query只查看在查询开始之前提交的数据,从不查看在查询执行期间提交的更改 并发事务

但在最后一句中,它指出:

还要注意,两个连续的SELECT命令可以看到不同的数据, 即使它们在单个事务中,如果其他 事务在第一次选择开始之后和之前提交更改 第二次选择开始


对我来说,这看起来很矛盾。有人能详细说明一下吗?两个SELECT查询如何在一个事务中看到不同的数据?交易不是孤立的吗?

是的,确实如此。为了避免这种情况,您需要使用更高的隔离级别:“可重复读取”。 如果需要完全隔离事务,甚至可以“序列化”。 请记住,隔离度越高,性能成本就越高

在这里您可以找到详细的解释:

下面是一个例子,它是如何发生的:

  • Connection1打开事务并使用 “选择*”
  • Connection2更新同一行并提交

  • Connection1再次读取同一行并获取更新的数据

  • 隔离级别是“readcommitted”,因此实际上所有提交的内容都对其他连接可见


    如果由于某种原因不能使用更高的隔离级别,有一种方法可以防止发生这种“意外”更新:您的连接1可以使用“选择…进行更新”。这将有效地锁定行,直到Connection1事务提交或回滚。因此,Connection2将等待此提交或回滚来更新行。

    没有矛盾。事务中的两个连续SELECT语句可能获取不同的结果。考虑这一点-你开始交易,然后发布 从emp中选择*; 你有两张唱片。 另一个会话将记录插入emp并提交。 在第一个会话中,您将再次发布 从emp中选择*; 你有3张唱片。这是读提交隔离级别的预期行为

    示例代码

    tmp=# begin ; 
    BEGIN
    tmp=# select * from emp;
     id 
    ----
      1
      2
    (2 rows)
    
    tmp=# select * from emp;
     id 
    ----
      1
      2
      3
    (3 rows)
    
    tmp=# commit;
    

    我的主要问题是
    两个SELECT查询如何在一个事务中看到不同的数据?
    而您的回答并没有真正的帮助,只是添加了一个示例,HTH。如果上面的内容还不够清楚,请询问更多细节。这意味着交易不是真正孤立的吗?它仍然可以看到其他事务提交的更改?它可能与未提交的更改隔离,但在postgresql中,它不可能以任何方式获取这些更改,而READ_COMMITTED是,仅与未提交的更改隔离。但是你仍然可以使用REPEATABLE_READ(这正是你想要的隔离)或者甚至是SERIALIZABLE(也可以排除幻象读取)。呃,在阅读文档时很容易迷失方向,完全可能导致矛盾。事实上,在你进入交易的本质之前,我认为打交易是一个最大的矛盾之一。我觉得人们对事务默认功能的假设应该是“可序列化”级别。