MYSQL中乐观锁的实现方法

54次阅读
没有评论

共计 2152 个字符,预计需要花费 6 分钟才能阅读完成。

MYSQL 中乐观锁的实现方法,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面丸趣 TV 小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

什么是 MVCC

MVCC 即 Multi-Version Concurrency Control,中文翻译过来叫多版本并发控制。

MVCC 是解决了什么问题

众所周知,在 MYSQL 中,MyISAM 使用的是表锁,InnoDB 使用的是行锁。而 InnoDB 的事务分为四个隔离级别,其中默认的隔离级别 REPEATABLE  READ 需要两个不同的事务相互之间不能影响,而且还能支持并发,这点悲观锁是达不到的,所以 REPEATABLE  READ 采用的就是乐观锁,而乐观锁的实现采用的就是 MVCC。正是因为有了 MVCC,才造就了 InnoDB 强大的事务处理能力。

MVCC 具体实现分析

InnoDB 的 MVCC, 是通过在每行记录后面保存两个隐藏的列来实现的, 这两个列,分别保存了这个行的创建时间,一个保存的是行的删除时间。这里存储的并不是实际的时间值, 而是系统版本号(可以理解为事务的 ID),每开始一个新的事务,系统版本号就会自动递增,事务开始时刻的系统版本号会作为事务的 ID. 下面看一下在 REPEATABLE  READ 隔离级别下,MVCC 具体是如何操作的。

首先创建一张表:

create table yang( id int primary key auto_increment, name varchar(20) );

假设系统的版本号从 1 开始.

INSERT

InnoDB 为新插入的每一行保存当前系统版本号作为版本号。*** 个事务 ID 为 1:

start transaction; insert into yang values(NULL, yang  insert into yang values(NULL, long  insert into yang values(NULL, fei  commit;

对应在数据中的表如下(后面两列是隐藏列, 我们通过查询语句并看不到)

SELECT

InnoDB 会根据以下两个条件检查每行记录:

InnoDB 只会查找版本早于当前事务版本的数据行(也就是, 行的系统版本号小于或等于事务的系统版本号),这样可以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或者修改过的.

行的删除版本要么未定义, 要么大于当前事务版本号(这可以确保事务读取到的行,在事务开始之前未被删除),  只有条件 1、2 同时满足的记录,才能返回作为查询结果.

DELETE

InnoDB 会为删除的每一行保存当前系统的版本号 (事务的 ID) 作为删除标识.

看下面的具体例子分析: 第二个事务,ID 为 2:

start transaction; select * from yang; select * from yang; commit;

假设 1:

假设在执行这个事务 ID 为 2 的过程中, 刚执行到(1), 这时, 有另一个事务 ID 为 3 往这个表里插入了一条数据; 第三个事务 ID 为 3;

start transaction; insert into yang values(NULL, tian  commit;

这时表中的数据如下:

然后接着执行事务 2 中的 (2), 由于 id= 4 的数据的创建时间(事务 ID 为 3), 执行当前事务的 ID 为 2, 而 InnoDB 只会查找事务 ID 小于等于当前事务 ID 的数据行, 所以 id= 4 的数据行并不会在执行事务 2 中的(2) 被检索出来, 在事务 2 中的两条 select   语句检索出来的数据如下:

假设 2

假设在执行这个事务 ID 为 2 的过程中, 刚执行到(1), 假设事务执行完事务 3 后,接着又执行了事务 4;

第四个事务:

start transaction; delete from yang where id=1; commit;

此时数据库中的表如下:

接着执行事务 ID 为 2 的事务 (2), 根据 SELECT   检索条件可以知道, 它会检索创建时间(创建事务的 ID) 小于当前事务 ID 的行和删除时间 (删除事务的 ID) 大于当前事务的行, 而 id= 4 的行上面已经说过, 而 id= 1 的行由于删除时间 (删除事务的 ID) 大于当前事务的 ID, 所以事务 2 的(2)select  * from yang 也会把 id= 1 的数据检索出来. 所以, 事务 2 中的两条 select 语句检索出来的数据都如下:

UPDATE

InnoDB 执行 UPDATE,实际上是新插入了一行记录,并保存其创建时间为当前事务的 ID,同时保存当前事务 ID 到要 UPDATE 的行的删除时间。

假设 3:

假设在执行完事务 2 的 (1) 后又执行, 其它用户执行了事务 3,4, 这时,又有一个用户对这张表执行了 UPDATE 操作:

第 5 个事务:

start transaction; update yang set name= Long  where id=2; commit;

根据 update 的更新原则: 会生成新的一行, 并在原来要修改的列的删除时间列上添加本事务 ID, 得到表如下:

继续执行事务 2 的(2), 根据 select 语句的检索条件, 得到下表:

还是和事务 2 中(1)select 得到相同的结果.

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注丸趣 TV 行业资讯频道,感谢您对丸趣 TV 的支持。

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-03发表,共计2152字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)