网站建设方案功能描述,软件开发模型螺旋模型,wordpress文章中调用自定义字段,成都网站制作公司电话文章目录 简介什么是MVCC快照读与当前读悲观锁的问题示例参考文献 简介
在MySQL中#xff0c;默认的隔离级别是可重复读#xff0c;可以解决脏读和不可重复读的问题#xff0c;但不能解决幻读问题。如果想要解决幻读问题#xff0c;就需要采用串行化的方式#xff0c;通过… 文章目录 简介什么是MVCC快照读与当前读悲观锁的问题示例参考文献 简介
在MySQL中默认的隔离级别是可重复读可以解决脏读和不可重复读的问题但不能解决幻读问题。如果想要解决幻读问题就需要采用串行化的方式通过牺牲数据库的并发事务处理能力将隔离级别提升到最高。
那有没有一种方式可以不采用锁机制而是只通过乐观锁的方式来解决不可重复度和幻读问题呢
确实有MVCC机制就是用来解决这个问题的。在多数情况下它可以替代行级锁降低系统的开销如InnoDB中就是默认开启MVCC机制的除此之外还有OracleDB2是采用多版本读的方式实现隔离级别但严格来讲不是MVCC。
大部分的RDBMS都会支持MVCC。
本节将主要介绍以下几部分
MVCC机制的思想是什么为什么RDBMS要采用MVCC机制只依靠悲观锁还不够么
什么是MVCC
MVCC的英文全称是Multiversion Concurrency Control中文翻译过来就是多版本并发控制系统。
顾名思义MVCC是通过数据行的多个版本管理来实现数据库的并发控制。
简单的说它的思想就是保存数据的历史版本。这样我们就可以通过比较版本号来决定数据是否显示出来具体的规则后面会讲基于这种乐观锁的机制我们在读取数据的时候不需要加锁也可以保证事务的隔离性。
先总结一下MVCC的具体作用
解决了读写之间的阻塞问题。通过MVCC可以让读写之间互相不阻塞即读的时候不会再阻塞写反之也是一样从而提高了事务的并发处理能力降低了死锁的概率。MVCC里采用的是乐观锁的思想所以读取数据时根本不用加锁即使是写数据的时候最多也是只锁定必要的行。降低了锁的数量自然也降低了死锁的概率。解决一致性读的问题。一致性读又叫做快照读当我们查询数据库在某个时间点的快照时只能看到这个时间点之前事务提交更新的结果而不能看到这个时间点之后事务的提交结果。
快照读与当前读
快照读读取的是快照数据不加锁的select语句都属于快照读如
SELECT * FROM player WHERE ...当前读读取的是最新数据而不是历史版本的数据。加锁的select或者对数据进行增删改查的时候都会进行当前读。
SELECT * FROM player LOCK IN SHARE MODE;
SELECT * FROM player FOR UPDATE;
INSERT INTO player values ...
DELETE FROM player WHERE ...
UPDATE player SET ...因此快照读实际上就是普通读而当前读包括了加锁的读取和DML操作。
悲观锁的问题示例
接下来我们以一个具体的例子来讲解一下采用悲观锁思想可能造成的问题。
比如说我们有个账户金额表 user_balance包括三个字段分别是 username 用户名、balance 余额和 bankcard 卡号。其中只有用户A和用户B有账户余额其他账户的余额都是0。
接着数据库管理员需要查询这张表里的总账户金额即执行下面语句
SELECT SUM(balance) FROM user_balance这个过程里用户A或者B自行开启了一个事务做互相转账。
当管理员事务和用户的事务时间上撞在一起的时候会出现什么情况呢
我们举两个例子例子均来源于参考文献。
例子一由于管理员事务的行级锁的存在导致用户A给用户B转账会存在等待时间。
如图 为了保证数据的一致性管理员事务在统计数据的时候会给用到的数据加上行级锁。 比如说用户A所在数据行被加锁之后用户A就不能再操作自己的记录了如果想做update只能等到管理员事务结束后锁被释放才能操作。
这就导致了用户A的体验很不好多了额外的等待时长。
例子二死锁。
过程如图 简单的说就是管理员在统计的时候用户B开启了一个事务给A转账。
管理员事务是一行一行边读边加锁它先读取用户A的数据于是持有了用户A数据的行锁接下来它应该再读取用户B的数据再持有用户B数据的行锁。
但是在它还没有读到用户B的数据之前用户B就开启了事务抢先对自己的记录进行了操作于是用户B持有了自己所在数据行的行锁。
等到管理员事务需要读用户B的数据时会发现数据行已经被锁上了咋整那就只能等呗于是管理员事务就开始等待用户B数据的锁被释放。
只要用户B的事务正常结束锁释放那么管理员事务就能继续加锁向下执行来完成统计。
但是用户B的事务并没有结束因为是给用户A转账因此它还需要update用户A的数据把多的钱update进去。但问题是用户A的数据已经被管理员事务加锁了用户B的事务如果想读该怎么办呢只能等管理员事务主动释放这个行锁。
于是场面就变成了管理员事务在等待用户事务释放B数据的行锁而用户事务在等待管理员事务释放A数据的行锁互不相让死锁了。
这个就是悲观锁的常见问题不过在基于乐观锁的MVCC里这种情况发生的概率会很低具体的我们下节会介绍。
参考文献
31丨为什么大部分RDBMS都会支持MVCC