尝试了解MVCC

时间:2019-09-01 13:54:35

标签: postgresql mvcc

我试图了解MVCC,但无法理解。例如。 Transaction1(T1)尝试读取一些数据行。在同一时间T2更新同一行。

交易流为

  

T1开始-> T2开始-> T2提交-> T1提交

因此,第一个事务获取它的数据库快照,并返回到用户将要在其上进行其他计算的结果。但是据我了解,客户获得了旧数据价值?据我了解,MVCC,在T1事务开始后,该事务不知道其他一些事务会更改数据。因此,如果现在用户在那之后进行了一些计算(不涉及数据库),那么他正在对错误的数据进行计算吗?还是我不对,第一笔交易有一些机制可以知道行已更改?

现在让我们更改交易流程。

  

T2beg-> T1beg-> T2com-> T1com

在2PL中,用户由于锁定而获得了较新版本的数据(T1必须等待释放互斥锁之后)。但是就MVCC而言,它仍然是旧数据,据我了解,PostgreSQL MVCC模型。因此,我可以获得陈旧的数据以换取速度。我对吗?还是我想念什么?

谢谢

3 个答案:

答案 0 :(得分:3)

是的,您可能会从数据库中读取一些旧数据(并发事务已被修改),然后基于此执行计算并将“过时的”数据存储在数据库中。

这不是问题,因为逻辑顺序比事务发生的实际顺序更重要:

如果T1读取了一些数据,然后T2修改了数据,然后T1根据读取的内容修改了数据库,则可以说T1在逻辑上发生在T2之前,并且没有不一致。

仅当T1和T2修改相同的数据时,您会得到异常:T1读取数据,T2修改数据,然后T1根据读取的内容修改相同的数据。这种异常称为“丢失更新”。

只能以最弱(默认)的隔离级别READ COMMITTED进行更新。

如果要更好地与并发活动隔离,则需要至少使用REPEATABLE READ隔离。然后,T1在尝试更新数据时会收到一个,您将不得不重复该事务。第二次尝试时,它将读取新数据,并且所有数据将保持一致。

答案 1 :(得分:0)

  

事务流是下一个T1开始-> T2开始-> T2提交-> T1提交。因此,第一个事务获取它的数据库快照,并返回到用户结果,他将在该结果上进行其他计算。但是据我了解,客户获得了旧的数据价值?

除非T1和T2尝试更新同一行,否则通常可以将其重新排序为:T1开始; T1提交; T2开始; T2提交;

换句话说,在T1做出决定的同时通过T2更改数据可能实现的任何不良业务结果,也可能在T1做出相同决定后立即通过T2更改数据来实现。

答案 2 :(得分:0)

事务 1 读取数据时,会将该数据的读取时间戳标记给事务 1。

如果事务 2 尝试读取相同的数据,它会检查数据的读取时间戳,如果数据的读取时间戳小于事务 2,则事务 2 被中止,因为 1 < 2 -- 1 之前到达那里我们,他们必须在我们之前完成。

在提交时,我们还会检查数据的读取时间戳是否小于提交事务。如果是,我们中止交易并使用新的交易 ID 重新开始。

我实际上已经在 J​​ava 中实现了 MVCC。 (请参阅 transactionrunnermvcc 代码)