首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >PostgreSQL - MVCC (多版本并发控制)-什么时候获得实际锁?

PostgreSQL - MVCC (多版本并发控制)-什么时候获得实际锁?
EN

Stack Overflow用户
提问于 2020-07-29 08:05:31
回答 1查看 450关注 0票数 3

根据我的理解,postgres使用两个额外的字段Xmin和Xmax来实现mvcc,假设我们有带有id和name列的Employee表。

下面是一些crud操作以及它们是如何并发工作的(考虑隔离级别= READ_COMMITTED),问题是何时在何处获得实际锁。

  1. Insert ->新事务插入新记录,在其他事务提交之前该记录不可见,因此在本例中不存在任何问题,也不需要锁或版本控制。假设id = 1,则插入name = "aa“。Postgres为mvcc =当前txn id (假设为100)和Xmax =0/null添加了两个额外列。

代码语言:javascript
运行
复制
id  |   name | Xmin | Xmax
------------------------------
1   |   aa   | 100  | null

具有并发读取的

  1. Update -

a)。一个新的事务开始将名称更新为"bb“(对于id = 1)。同时,还有另一个事务开始读取相同的数据。

b)。一个新的元组( postgres中表示一行的不可变对象)将使用Xmin =当前事务id (假设200)和Xmax = null以及id = 1、name = bb创建。此外,id =1的旧版本也会被更新为具有Xmax = 200。returns看到Xmin = 100的旧版本的数据并返回。在这种情况下是否需要任何锁?我认为不是,但它可能会更新旧元组的Xmax.

下面是多个版本的相同记录(只是为了解释),最新版本具有Xmax = null。

代码语言:javascript
运行
复制
id  |   name | Xmin | Xmax
------------------------------
1   |   aa   | 100  | 200
1   |   bb   | 200  | null

具有并发更新的

  1. Update -

a)。事务(使用txn id = 300)开始将id =1更新为name = cc。另一个事务(txn id = 400)开始将相同的记录(id = 1)更新为name = dd。如果这个场景通过创建新元组和标记旧元组的Xmax来以同样的方式进行,那么我认为它会产生问题,因为300和400都将创建一个新的元组并标记旧元组的Xmax = txn id。在这种情况下,更新可能会松动。

在这个场景中,排他锁是由第一个txn和其他并发更新txns获得的,等待任何正在进行的txn完成,或者有其他一些处理它的方式?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-29 16:40:22

插入->新事务插入一个新记录,在其他事务提交之前它是不可见的,因此在这种情况下不存在任何问题,也不需要锁或版本控制。

这不是真的。插入的元组在插入时被锁定。例如,如果有一个唯一的约束,而其他人试图插入一个冲突的元组,这就很重要了。

使用并发

进行Read....Is更新--在本例中需要任何锁

当xmax正在更新时,在保存元组的缓冲区上有一个“轻量级”锁,该锁将在字段更新后立即释放(在事务期间不保持)。这个轻量级锁包括一个屏障,以确保任何其他进程都会看到更改,而不是看到过时的缓存版本。

读取器将看到xmax为0并返回元组,或者看到xmax为200并看到200尚未提交,并且返回元组,因为它知道xmax = 200表示的锁不适用于它,这仅仅是读取器。

更新与并发更新..。

将其id写入即将过时的元组的xmax的第一个进程将获胜。第二个将在xmax中看到其他人的有效id,并阻塞直到其他事务提交或回滚,然后决定要做什么。由于存放元组的缓冲区上的锁很轻,所以它们都不能在没有注意到彼此更改的情况下更新xmax。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63149069

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档