说我想在读取提交模式下执行以下事务(在postgres中)。
T1: r(A) -> w(A)
T2: r(A) -> w(A)
如果按此顺序调用的操作:
r1(A)->r2(A)->w1(A)->c1->w2(A)->c2
我很期待T2必须等待r(A)。因为T1会在第一次读取时为A设置一个独占锁,因为它想在以后写入它。但是MVCC没有读锁?
现在我有两个问题:
如果我使用JDBC读取一些数据,然后执行separte命令来插入读取数据。数据库如何知道只有在读取时才必须进行独占锁定?据我所知,在2PL中不允许将读锁增加到写锁。
我认为我的假设是错误的......这种情况在哪里等待或是一次交易被杀?读取未提交不应该允许丢失更新,但我看不出这是如何工作的。
如果有人可以帮助我,我会很高兴。感谢答案 0 :(得分:1)
“但是MVCC没有读锁?”
MVCC是一个不同的野兽。 MVCC中没有“锁定”,因为在该场景中,系统维护同时运行的事务可能需要的单行的多个版本。一行中的“前内容”不会“因更新而丢失”(即物理覆盖和销毁),从而确保读者无法看到“新更新”,通过将该读者的查询“重定向”来解决“昔日内容”,未被锁定(因此称为“快照隔离”)。请注意,MVCC原则上不能应用于更新事务。
“如果我使用JDBC读取一些数据,然后执行单独的命令来插入读取数据。数据库如何知道它只在读取时必须进行独占锁定?增加读取锁定到写入据我所知,2PL中不允许锁定。“
你错了2PL。 2PL意味着获取的锁永远不会在提交时释放。这并不意味着现有的锁无法加强。顺便说一下:这就是为什么隔离级别如“游标稳定性”不是2PL:它们确实在提交时间之前释放读锁。
答案 1 :(得分:0)
PostgreSQL中的默认事务模式是READ COMMITTED,但READ COMMITTED 不提供您正在寻找的序列化级别。
您正在寻找SERIALIZABLE交易级别。在阅读SET TRANSACTION上的PostgreSQL文档后,查看Transaction Serialization Levels命令,特别是SERIALIZABLE mode。 PostgreSQL的MVCC docs也值得一读。
干杯。
答案 2 :(得分:0)
我很期待T2必须等待r(A)。因为T1会在第一次读取时为A设置一个独占锁,因为它想在以后写入它。但是MVCC没有读锁?
如果在select语句中指定for update
,则会有写锁定。在这种情况下,如果r2(A)试图锁定与r1(A)相同的行,它将等待读取。
http://www.postgresql.org/docs/9.0/interactive/explicit-locking.html
如果两个事务开始并最终请求彼此已锁定的行,则会发生死锁:
r11(A) -> r22(A) -> r12(A) (same as r22) vs r21(A) (same as r11) -> deadlock