当前位置: 首页 > 知识库问答 >
问题:

SELECT 能否使用“读取已提交隔离级别”在一个事务中获取不同的结果?

朱英范
2023-03-14

下面是postgresql 9.6文档中关于读取提交隔离级别的完整段落:

读取提交是PostgreSQL中的默认隔离级别。当事务使用此隔离级别时,SELECT查询(没有FOR UPDATE/SHARE子句)只能看到查询开始前提交的数据;它永远不会看到未提交的数据或并发事务在查询执行期间提交的更改。实际上,SELECT查询会在查询开始运行时看到数据库的快照。但是,SELECT确实会看到在其自己的事务中执行的先前更新的影响,即使它们尚未提交。另请注意,如果其他事务在第一个SELECT启动后和第二个SELECT启动前提交更改,即使它们在单个事务中,两个连续的SELECT命令也可以看到不同的数据。

所以基本上:

SELECT查询只能看到查询开始前提交的数据,永远不会看到并发事务在查询执行期间提交的更改。

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

另请注意,如果其他事务在第一个SELECT启动后和第二个SELECT启动前提交更改,即使它们在单个事务中,两个连续的SELECT命令也可以看到不同的数据。

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

共有2个答案

盛嘉
2023-03-14

没有矛盾。事务中的两个连续SELECT语句可能会获取不同的结果。考虑这一点-您开始交易,然后发出
从emp中选择*;你得到两张唱片。另一个会话将记录插入emp并提交。在第一个会话中,您再次发出select*from 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;
仲孙夕
2023-03-14

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

在这里您可以找到详细的解释:https://www.postgresql.org/docs/9.1/static/transaction-iso.html

这是一个如何发生的例子:

> < li>Connection1打开事务,并使用“select *”从表1中读取一行 < li>

Connection2更新同一行并提交

连接 1 再次读取同一行并获取更新的数据

隔离级别是“读取提交”,因此从字面上看,提交的所有内容对其他连接都是可见的。

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

 类似资料:
  • 在我的airflow升级到2.0.0(然后是2.0.1)并且调度程序扩展到3个节点之后,奇怪的事情发生了: DAGRUNN成功,但根本没有计划任务实例 任务失败,主机名为空(https://github.com/apache/airflow/issues/13692) 任务设置为“upstream_failed”,而上游任务成功(https://github.com/apache/airflow/

  • 本文向大家介绍Mysql事务隔离级别之读提交详解,包括了Mysql事务隔离级别之读提交详解的使用技巧和注意事项,需要的朋友参考一下 查看mysql 事务隔离级别 可以看到当前的事务隔离级别为 READ-COMMITTED 读提交 下面看看当前隔离级别下的事务隔离详情,开启两个查询终端A、B。 下面有一个order表,初始数据如下 第一步,在A,B中都开启事务 第二步查询两个终端中的number值

  • 我有一个查询如下在PostgreSQL: 许多工作人员试图一次处理一项工作(这就是为什么我有限制为1的子查询)。在此更新之后,每个工作人员都会获取有关id的信息并处理工作,但有时他们会获取相同的工作并处理两次或更多次。隔离级别已读提交。 我的问题是,我如何保证一个工作将被处理一次?我知道有这么多的帖子,但我可以说我已经尝试了其中的大部分,但都没有帮助(); 我已尝试选择更新,但它导致了死锁的情况

  • 我将spring应用程序连接到smartbaer servicev,在那里创建了虚拟数据源(Postgres)。 驱动程序类: 连接字符串(本地servicev虚拟服务器url): 应用程序.属性:- spring.datasource.driver-class-name=com.smartbear.servicev.jdbc.driver.jdbcvirtdriver spring.dataso

  • 本文向大家介绍事务的隔离级别有哪些?相关面试题,主要包含被问及事务的隔离级别有哪些?时的应答技巧和注意事项,需要的朋友参考一下 SQL 标准定义了四个隔离级别: READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。 READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重

  • 我有一个对具有 SQL API 的 Cosmos 容器的长期运行查询,该查询需要 10 分钟以上才能完成。有没有办法将数据库的隔离级别设置为“可重复读取”或“可序列化”,以避免幻像读取,如这里所定义的那样? 我知道我们可以为 Cosmos DB 设置一致性级别,但它仅适用于地质副本之间的读/写一致性,而不适用于事务隔离。