Database 读取未提交的mvcc数据库

Database 读取未提交的mvcc数据库,database,postgresql,transactions,mvcc,Database,Postgresql,Transactions,Mvcc,假设我想在读提交模式下(在postgres中)执行以下事务 如果按此顺序调用操作: r1(A)->r2(A)->w1(A)->c1->w2(A)->c2 我认为T2必须在r(A)处等待。因为T1会在第一次读取时为A设置一个独占锁,因为它希望稍后再写入它。但是MVCC没有读锁吗 现在我有两个问题: 如果我使用JDBC读取一些数据,然后执行separte命令插入读取的数据。当数据库仅在读取时,它如何知道必须进行独占锁定?据我所知,在2PL中不允许将读锁增加到写锁 我认

假设我想在读提交模式下(在postgres中)执行以下事务

如果按此顺序调用操作:

r1(A)->r2(A)->w1(A)->c1->w2(A)->c2
我认为T2必须在r(A)处等待。因为T1会在第一次读取时为A设置一个独占锁,因为它希望稍后再写入它。但是MVCC没有读锁吗

现在我有两个问题:

如果我使用JDBC读取一些数据,然后执行separte命令插入读取的数据。当数据库仅在读取时,它如何知道必须进行独占锁定?据我所知,在2PL中不允许将读锁增加到写锁

我认为我的假设是错误的。。。此场景在何处等待或一个事务被终止?Read uncommitted不允许丢失更新,但我看不出这是如何工作的


如果有人能帮助我,我会很高兴的。谢谢

PostgreSQL中的默认事务模式是读提交,但是读提交不提供您所需的序列化级别

您正在寻找可序列化事务级别。在阅读PostgreSQL的文档之后,请查看该命令,特别是。PostgreSQL也值得一读

干杯

我认为T2必须在r(A)处等待。因为T1会在第一次读取时为A设置一个独占锁,因为它希望稍后再写入它。但是MVCC没有读锁吗

如果在select语句中为update指定
,则会有写锁。在这种情况下,如果r2(A)试图锁定与r1(A)相同的行,它将等待读取

如果两个事务开始并最终请求对方已锁定的行,则会发生死锁:

r11(A) -> r22(A) -> r12(A) (same as r22) vs r21(A) (same as r11) -> deadlock
“但是MVCC没有读锁吗?”

MVCC是另一种野兽。MVCC中没有“锁”,因为在这种情况下,系统维护并发运行的事务可能需要的单个行的多个版本。行的“以前的内容”不会“因更新而丢失”(即物理覆盖和销毁),因此,通过“重定向”读者的查询到未锁定的“以前的内容”(因此称为“快照隔离”)来确保读者看不到“新的更新”。请注意,原则上,MVCC不能应用于更新事务

“如果我使用JDBC读取一些数据,然后执行一个单独的命令来插入读取的数据。数据库如何知道它在仅读取时必须进行独占锁定?据我所知,在2PL中不允许将读取锁定增加为写入锁定。”


关于2PL,你错了。2PL意味着获取的锁在提交之前不会被释放。这并不意味着现有锁无法加固。顺便说一句:这就是为什么像“游标稳定性”这样的隔离级别不是2PL的原因:它们确实在提交时间之前释放了读锁。

谢谢,您能解释一下读提交对这些事务有什么作用吗?我认为如果阅读提交,则不可能丢失更新?不,很有可能。我不想说RTFM,但我无法比文档更好地解释它。请务必阅读13.2.1的最后两段。您可能还想查看PostgreSQL 9.1(beta1 now),它添加了真正的可序列化事务隔离级别。只要我写下我读到的所有内容,快照隔离就可以了。当事务的写入集不分离时,一个将被丢弃。strict 2PL实际上不允许提升锁。否则,另一个事务可以读取原始数据,然后第一个事务升级为写锁,然后在写入后提交。现在事务2写入并提交。这会导致事务1的更新丢失。如果它立即请求写锁,事务2将不得不等待。但现在我了解了MVCC或快照隔离。写入集必须是不相交的。所以你把你读到的东西都写下来就好了。
r11(A) -> r22(A) -> r12(A) (same as r22) vs r21(A) (same as r11) -> deadlock