MVCC (多版本并发控制) part 1

原文链接: https://15721.courses.cs.cmu.edu/spring2018/

 

Compare-and-Swap(CAS) 乐观锁实现机制

  • 原子操作,认为某一内存位置M的值应为V,如果是,则将位置M的值更新为V’,否则,操作失败

MVCC (多版本并发控制) part 1_第1张图片

                           图1.1 

内存位置M的值为20,compare value为20,两者相等,如图1,将位置M更新为30,如图2

MVCC (多版本并发控制) part 1_第2张图片

                    图 1.2

内存位置M的值为30,compare value为25,两者不相等,如图3,该操作失败

MVCC (多版本并发控制) part 1_第3张图片

                     图 1.3

  • 可以通过intrinsic function call(内部函数调用)完成,无需写machine code,编译器知道如何转化为instruction

 

Isolation levels(隔离级别)

Serializability(序列化隔离级别):可以忽略并发场景,但并行度过低,性能受限

事务隔离级别控制该事务暴露给其他并发事务的行为

可能会引起如下现象:脏读、不可重复读、幻读等。

脏读:事务1 insert一条数据,但未提交,事务2可以select到这条未提交的数据,一旦事务1发生回滚,该条数据则为脏数据(mysql undo),称为脏读,即读到为提交的数据。

不可重复读:事务1 select某一条数据,得到一个结果,事务2 update该条数据并已提交,事务1此时再去select该条数据,得到的结果和上次select的结果不一致。不可重复读主要针对update。

幻读:事务1 select 某一组数据,如select age小于15的数据,得到一组结果,事务2 insert 一条数据,该数据age 小于15,事务1 再次select age小于15的数据,发现多一条记录。幻读主要针对insert

 

基本的事务隔离级别如下:

Serializable(序列化):无幻读、所有读可重复、无脏读

Repeatale reads(可重复读):可能存在幻读(phantoms)

Read commited(提交读):可能存在幻读、不可重复读

Read uncommited(未提交读):所有都有可能发生

 

如图2.1 是主流数据的事务隔离级别:

MVCC (多版本并发控制) part 1_第4张图片

                    图 2.1

事务隔离级别基于SQL-92标准,只关注与基于2PL(2阶段锁)的数据库系统(DBMS),如下两个级别与2PL无关

 

CURSOR STABILITY:

--DB2 的默认隔离级别,

--cursor(游标)是一个pointer inside database system of points out whatever data itms a tuple that the query is operating on that moment,I need to access,the cursor will acquire locks with the things that wants to access,即如果需要扫描2个tuples时,游标会找到第一个tuple,并对其加锁,然后做操作,做完操作后释放该锁,然后再去获取第二个tuple的游标锁,然后做操作,然后释放该锁)

--对于2PL在growing phase获取所有锁,如果释放一个锁,进入shrinking phase,you can never go back and acquire another lock,but in cursor locking you can do that,由于only one query can hold one cursor at a time,所以不用担心死锁

--介于读提交和可重复读之间,强于读提交是因为可以防止update丢失现象

--可以防止update丢失现象(but not laways)

--update 丢失:如图2.2

假设在一个单core系统中,txn1 read(A)获取游标锁并释放,txn2 write(A) 获取游标锁并释放,txn1 write(A) 获取游标锁并释放,txn1 commit,稍后txn2 commit。虽然txn2 commit比txn1晚,但是只能看到txn1 write(A),而txn2 write(A) 被txn1 重写了,所以txn2 的update似乎丢失了

如果txn1知道将会write(A),就会一直hold the cursor lock,txn2会阻塞,txn1 先提交,然后txn2 执行,就不会出现update丢失的现象。

所以CURSOR STABILITY可以防止update丢失现象,but not always。

MVCC (多版本并发控制) part 1_第5张图片

MVCC (多版本并发控制) part 1_第6张图片

 

MVCC (多版本并发控制) part 1_第7张图片

MVCC (多版本并发控制) part 1_第8张图片

              图 2.2  update丢失

 

SNAPSHOT ISOLATION(快照隔离级别):

--参考tidb/cockroachDB,tidb默认级别为SI,cockroachDB支持SI/SSI两种级别

--保证事务中所有的read,可以查看到事务开始时,数据库存在的一致性快照,可以理解为对每个事务start_timestamp做一致性快照,该快照应用于该事务的所有read

--since that snapshot,事务只有在write与其他的并发update无冲突时才能提交

--易受写偏序(write skew)现象影响

--写偏序:如图2.3

假如txn1想把白块变成黑块,txn2想把黑块变成白块,当txn1和txn2并发时,他们事务开始时拿到的一致性快照都是上半黑下半白,当txn1和txn2 commit后,变成了上半白下半黑。

但是如果两个事务序列化执行,得到的操作,应该是txn1先把白的变成黑的,txn2再把黑的变成白的。最后的结果是全白。即由于两者各自拿到了一致性快照,因为无法知晓其他事务的修改,提交时又不冲突,而造成的最终结果不一致。

MVCC (多版本并发控制) part 1_第9张图片

MVCC (多版本并发控制) part 1_第10张图片

MVCC (多版本并发控制) part 1_第11张图片

MVCC (多版本并发控制) part 1_第12张图片

                  图2.3 写偏序

几种事务隔离级别的关系

MVCC (多版本并发控制) part 1_第13张图片

            图2.4 几种事务隔离级别的关系

MVCC (多版本并发控制) part 1_第14张图片

你可能感兴趣的:(mysql)