mysql 锁

    xiaoxiao2025-02-25  53

    InnoDB 的行锁是实现在索引上的,而不是锁在物理行记录上。也就是说,如果访问没有命中索引,也无法使用行锁,将要退化为表锁。所以InnoDB 务必建好索引,否则锁粒度较大,会影响并发

     

    mysql锁主要有三类: 行锁, 间隙锁, 临键锁

    构建表test(id pk,num key)。

    idnum33557710714916102013

    记录锁(行锁)

    它封锁索引记录,例如下面的查询语句:

    1

    select * from xttblog where id=1 for update;

    它会在 id=1 的索引记录上加锁,更新事务则会阻塞等待。

    select * from t where id=1 for update;

    只会封锁记录,而不会封锁区间

    需要说明的是,如果是下面的查询语句:

    1

    select * from xttblog where id=1;

    则是快照读(SnapShot Read),它并不加锁

    间隙锁

    why:主要是实现可重复读, 消除幻读

    how:1. 当进行范围当前读时 2. 当进行等值查询而且是非唯一索引时

    1:唯一索引/主键+范围查询 锁住范围内的已存在的符合要求的行,还会加上范围内的gap,例子如下:

    select * from test where id between 6 and 16 for update;//该句锁id=7,10,15这三行, 还会锁id=8,9,11,12,13,14这几行, 此时另一个事务是插不进去id=8,9,11,12,13,14的数据的。

    2:普通索引+绝对范围(不存在等于的情况)查询 锁住范围内的已存在的符合要求的,还会加上范围内的gap,例子如下:

    事务A: select * from test where num>10 for update;//该句锁定范围(10,正无穷),不包括10。 事务B: insert into test (id,num) values(15,10)//成功 update test set num=18 where id=16//成功 * insert into test (id,num) values(17,10)//失败* insert into test (id,num) values(17,9)//成功*

    3:普通索引+等值查询 除了锁定值外,还会加上左右两侧的gap,例子如下:

    事务A: select * from test where num = 7 for update;//该句除了锁定(5,9) 事务B: insert into test (id,num) values(4,5)//成功 update test set num=18 where id=5//成功 * insert into test (id,num) values(6,5)//失败* insert into test (id,num) values(6,20)//成功* insert into test (id,num) values(6,8)//失败

       

    对于普通索引需要注意的是,锁范围的边缘值可以更新,但不允许在锁定范围内插入与边缘值相等的行。如例子中加*的sql。另外,对于2,如果是 select * from test where num>=9;就会锁定范围(7,正无穷),而不是[9,正无穷),但是select * from test where id>=16;就会锁定范围[16,正无穷),而不是(14,正无穷)。

    临键锁(mysql如果加锁的话 默认策略)https://www.cnblogs.com/zhoujinyi/p/3435982.html

    临键锁:记录锁与间隙锁组合起来用就叫做Next-Key Lock,就是将键及其两边的的间隙加锁(向左扫描扫到第一个比给定参数小的值, 向右扫描扫描到第一个比给定参数大的值, 然后以此为界,构建一个区间)。 利用Next-Key Lock可以阻止其它事务在锁定区间内插入数据,因此在一定程度上解决了幻读问题

    select…from for update 在扫描到的任何索引记录上加排它的next-key lock,对于扫描到的主键/唯一索引加记录锁 ,对于不存在的加间隙锁

    update…where delete from…where 在扫描到的任何索引记录上加next-key lock,对于扫描到的主键/唯一索引加记录锁 ,对于不存在的加间隙锁

    总结: mysql默认使用mvcc支持高并发, 如果要加锁会使用临建锁。

     

    意向锁

    问题:一个事务是对一条记录加锁, 另一个事务是对整个表进行修改, 另一个事务要遍历每条记录是否有锁,影响性能

    解决: mysql会在一条记录加锁时, 同时会在表级添加意向锁,这样另一个事务可以判断是否有意向锁,不用判断每条记录。

    意向锁仅仅是一个辅助标识, 不会对数据造成实际上的阻塞

    普通锁,本质是串行执行

    读写锁,可以实现读读并发

    数据多版本,可以实现读写并发

    redo日志保证已提交事务的ACID特性,设计思路是,通过顺序写替代随机写,提高并发;

    undo日志用来回滚未提交的事务,它存储在回滚段里;

    引自:https://www.xttblog.com/?p=3053

    https://blog.csdn.net/weixin_38597669/article/details/89405337

    最新回复(0)