我试图了解MVCC,但无法理解。例如。 Transaction1(T1)尝试读取一些数据行。在同一时间T2更新同一行。
交易流为
T1开始-> T2开始-> T2提交-> T1提交
因此,第一个事务获取它的数据库快照,并返回到用户将要在其上进行其他计算的结果。但是据我了解,客户获得了旧数据价值?据我了解,MVCC,在T1事务开始后,该事务不知道其他一些事务会更改数据。因此,如果现在用户在那之后进行了一些计算(不涉及数据库),那么他正在对错误的数据进行计算吗?还是我不对,第一笔交易有一些机制可以知道行已更改?
现在让我们更改交易流程。
T2beg-> T1beg-> T2com-> T1com
在2PL中,用户由于锁定而获得了较新版本的数据(T1必须等待释放互斥锁之后)。但是就MVCC而言,它仍然是旧数据,据我了解,PostgreSQL MVCC模型。因此,我可以获得陈旧的数据以换取速度。我对吗?还是我想念什么?
谢谢
答案 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 重新开始。
我实际上已经在 Java 中实现了 MVCC。 (请参阅 transaction、runner 和 mvcc 代码)