暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

让SQL飞:InnoDB下的锁策略

赵小哥 2020-08-20
580

所谓的锁策略,就是在锁开销与安全性之间寻求平衡。


为了表述简洁,使用了一些缩写,大概标明一下:

  • RC:Read Committed

  • RR:Repeatable Read

  • Mvcc:Multi-Version Concurrency Control

  • RL:Record Lock

  • TL:Table Lock

  • GL:Gap Lock

  • RDBMS:Relational DataBase Management System

  • 2PL:Two-Phase-Locking


先贴一张MySQL的架构图,有助于下面的理解:



事务的四种隔离级别不做赘述,今天主要讨论的是RC级别和RR级别;

RC与RR的并发控制均由Mvcc实现,Mvcc是乐观锁中的一种实现方式,所以在这两种隔离级别下读不加锁写加锁,且select模式为snapshot read(与之相对current read);

Mvcc下,start transaction 将带一个version,version递增:

  • 查找:读取记录的版本号等于当前的版本号

  • 增加:插入记录,将创建列的版本号置为当前的版本号

  • 删除:将记录的删除列的版本号置为当前的版本号

  • 更新:insert + delete

细节请查阅相关资料。


今天我们做一些小的测试,在测试之前我们需要在脑海中构建一个模型,模型的作用是将复杂的现实世界简单化,然后来解释现实世界,放在这里同样适用,所以我们今天不考虑复杂的情况;


我们知道,InnoDB中是支持RL的,而RL锁的是索引列,若无索引,则锁定表内的所有记录(并不是TL,TL在Server实现);

首先创建一张表,然后插入20条记录:

    Create Table: CREATE TABLE `tb_zhaojn` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT,
    `age` int(10) NOT NULL,
    `name` varchar(255) NOT NULL,
    PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8


    insert into tb_zhaojn (age,name) values(0,"0");
    ...
    insert into tb_zhaojn (age,name) values(19,"19");

    下面在RC级别下做测试;

    在此之前,需要先设置一下隔离级别,MySQL的默认隔离级别是RR;


    另外再开启一个会话窗口,同样地设置,这里就不贴图了;

    第一个session做一个update;


    第二个session做一个update;

      update tb_zhaojn set name = 'b' where age = 2;

      结果会如何呢?可能你会觉得,session2将阻塞,因为没有索引,session1在update1时将锁定所有的记录,实际上并不是这样的;

      这是为什么呢?我们知道,RDBMS在处理事务时遵循2PL协议,但实际上,MySQL为了提高性能,也会违背此协议;在没有索引时,session1的确在Storage Engine中锁定了所有的记录,然后将结果返回给Server层;Server层过滤,将不符合条件的记录释放锁,从而提高数据库的并发性


      下面在RR级别下做测试;

      首先将两个session的置回RR;

        set transaction isolation level repeatable read;


        同样地,先在第一个session中执行;

        随后在第二个session中执行;

        我们发现session2阻塞了,为什么呢?因为RC级别解决的是脏读,不读取到其他事务中未提交的数据即可,所以仅仅由Mvcc即可实现;而RR级别解决的是幻读,仅仅锁定某些符合条件的记录只能保证该记录不被修改,却阻止不了新记录的插入;在RR事务中,解决幻读,直白地说就是阻止某些insert,是由Next-Key实现的(RL + GL),若条件列没有索引,就无法确定匹配范围,将所有记录上锁之后,并在表的头到尾加上Gap锁;

        倘若有了索引,那么在索引列上加RL,在索引起始与结束处加GL就可以了,现在来看下面的测试;

        session1;

        session2;

        和我们所预想的一样;


        欢迎一起讨论!

        最后修改时间:2020-08-20 17:27:00
        文章转载自赵小哥,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

        评论