Repeatable read isolation level 只能看见transaction开始前提交的数据;看不见未提交的数据和在当前transaction执行当中,其他并发transaction提交的数据。在同一个transaction内,当前命名可以看到上一条语句执行的结果。在PostgreSQL里,repeatable read解决了出serialization anomalies外所有的缺陷。在标准里面,只说了具体数据库的实现中各个的isolation level最少要处理哪些缺陷,没说不能多处理缺陷。
快照在transaction的第一条 non-transaction-control-statement产生,而不是当前sql语句。因此,在同一个transaction中,连续的select语句可以看到相同的数据。比如,在自己的transaction执行当中,是看不到其他transaction提交的数据。
|
sex |
name |
|
male |
李雷 |
|
female |
韩梅梅 |
|
Repeatable Read transaction1 |
Repeatable Read transaction2 |
|
Begin: |
Begin: |
|
Select * from user where sex=’male’; 查出:李雷 |
|
|
|
Insert into user (‘Jack’, ‘male’) |
|
|
Commit; 提交以后,transaction1 可见Jack。不提交就不可以,所以叫read committed |
|
Select * from user where sex=’male’; 查出:李雷,看不见Jack |
|
如果要用这个level,应用需要使用重试transaction机制,来应对serialization failures
|
Repeatable Read transaction1 |
Repeatable Read transaction2 |
|
Begin: |
Begin: |
|
|
Update user set name=’Dear’+name where sex=’male’ |
|
Update user set name=’Mr.’+name where sex=’male’;
|
Commit; 假设在transaction1阻塞后执行的commit,。 |
|
|
|
|
以上逻辑同样适用于delete,select for update 和 select for share |
|
|
|
|
UPDATE, DELETE, SELECT FOR UPDATE, and SELECT FOR SHARE在查询目标数据方面和select的情况一样:从transaction开始的时候,生成的数据库快照里找。如果在transaction执行中,被查出来待修改的数据被其他并发transaction修改提交或者回滚了,相应的当前transaction就会回滚或者继续执行。
报错信息:ERROR: could not serialize access due to concurrent update
Repeatable read transaction 不能修改或者锁被其他transaction修改的行。
当应用收到以上异常,应该回滚transaction并重新发起。Transaction会重新获取快照,数据就会保持一致性。
只有更新数据的transaction需要重试,只读的transaction不会有serialization conflicts.
|
Transaction1 |
Transaction2 |
|
Begin; 获取当前数据库快照 |
Begin; 获取当前数据库快照 |
|
|
Update user set name=’张三’ where id=1 |
|
Select * from user where id=1 这条数据已经被transaction2修改,等待transaction2提交 |
|
|
|
Commit; |
|
Id=1这条记录已被修改,事务回滚 |
|
本文深入探讨了数据库事务隔离级别中的重复读(Repeatable Read),解释了它如何确保事务内部数据的一致性,即使在高并发环境下也能避免脏读、不可重复读等问题。文章通过具体的例子说明了在PostgreSQL中重复读隔离级别的行为,以及如何通过重试机制解决序列化冲突。

被折叠的 条评论
为什么被折叠?



