MySQL——锁机制简述

  • 锁结构
    MySQL的锁是在内存中生成一个锁结构,如果要访问一个记录先检查是否在内存中存在锁结构然后再进一步打算。
  • 前言
    常规的查询语气中不会加锁而是会根据MVCC访问,除非显式的加锁下面讨论的是读写都需要加锁的情况,常规不做其他声明的写语气中会加锁保证不会发生脏写,也就是对记录做修改时先加锁。
  • 共享锁(shared locks)S锁
    大家共享的意思,如果一个事务对记录加了共享锁,那么其他事务也可以再加共享锁后进行访问,当然既然大家共享了也就是有共享锁存在时不可以加独占锁需要等待所有共享锁释放。读操作需要加共享锁
  • 独占锁(排他锁)(Exclusive Locks)X锁
    也就自己占有,如果加了独占锁就是说独占有其他事务想要访问都不行,不可以再进行加共享锁也不可以加独占锁,都要等待独占锁释放。修改操作需要需要加独占锁。
  • 锁的粒度
    有表级锁、行级锁。表级锁对整个表进行加锁当然性能会下降堵塞率会更高,但有些需求得必须加比如ALTER TABLE、DROP TABLE。行级锁就是对记录锁常用。
  • 意向锁
    分共享意向和独占意向锁(IS和IX锁),属于表级锁,当事务在记录上加锁时先在表级加上意向锁,表明表里面有锁,它们的提出仅仅为了在之后加表级别的S锁和X锁时可以快速判断表中的记录是否被上锁,以避免用遍历的方式来查看表中有没有上锁的记录,也就是说其实IS锁和IX锁是兼容的,IX锁和IX锁是兼容的。
  • AUTO-INC锁
    表级锁,记录都会有一个AUTO_INCREMENT属性,没有声明也在隐藏列里,所以为了确保每次插入后自增不重复需要一条一条插入,所以一条插入语气(每条插入语气,而不是一个事务和之前不一样)都会对表进行加AUTO-INC锁,当其他插入语气遇到这个锁时会堵塞等待,所以保证了不重复和递增。当然还有一种保障机制是经量锁,就是说生成自增属性得值后就释放锁不需要等到插入结束只需要生成自增列的值,用那种方式有一个系统变量可以设置。
  • 上边是理论,下边InnoDB具体实现
  • LOCK_REC_NOT_GAP锁
    也就是InnoDB里面的行锁,记录锁Record Locks,有共享记录锁和独占记录锁之分。
  • LOCK_GAP
    也就是gap锁,无法对新加的记录加的是Record Locks,也就是说读一个区间的记录后如果如果是新插入数据的是可以插入的因为没有锁,只是锁了单条记录,然后再次读取该区间时也会读取到新加的记录也就是幻读。InnoDB解决这一现象的办法就是读取的时候不给加入也就是提出了gap锁,这个锁的作用是比如给某个记录加锁了的话就不给在该记录的前面的间隙里插入插入新值,需要等待释放锁。
  • Next-Key Locks
    上面两种的混合锁,它既能保护该条记录,又能阻止别的事务将新记录插入被保护记录前边的间隙。
  • 插入意向锁
    InnoDB当插入的时候处理判断是否有gap锁外不会加任何锁,但当判断有gap锁的时候就会生成一个插入意向锁然后等待gap锁释放然后唤醒。感觉这个插入意向锁处理唤醒没啥用。
  • 隐式锁
    因为插入不会主动加任何锁结构,所以当一个事务插入后没有提交,另一个事务读取了及时脏读,修改了就是脏写,是不允许发生的。所以就有了隐式锁。就是说当一个事务要对某记录进行加S锁读取时或者X锁,反正就是要锁时先判断一下该记录的事务ID,如果时还在活跃的事务ID就帮忙加一个X锁(这个锁属于插入这个记录的),然后自己创建锁等待。这就是隐式锁
  • 读操作
    如果不显示的写加锁查询记录,READ UNCOMMITTED下直接读取最新就好,在READ COMMITTED、REPEATABLE READ下就是直接用的MVCC,在SERIALIZABLE下当然查询前先加S锁,当然也可以显示在sql语气加锁。
  • 插入
    插入和上面一样,如果有gap先生成一个插入意向锁等待,没有直接插入,不过注意当要读取刚插入的记录时会先判断时候加隐式锁。
  • 修改
    由于不会允许出现脏写,所以修改操作什么隔离级别都会加X锁。(插入时的隐式锁也共同保证不会脏写)
  • 注意
    InnoDB行锁是通过给索引上的索引项加锁来实现的,InnoDB 这种行锁实现特点意味着:

(1)只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB 将使用表锁。

(2)由于MySQL的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但是如果是使用相同的索引键,是会出现锁冲突的。

(3)当表有多个索引的时候,不同的事务可以使用不同的索引锁定不同的行,另外,不论是使用主键索引、唯一索引或普通索引,InnoDB 都会使用行锁来对数据加锁。(虽然使用的是不同的索引,但是如果记录已经被其他session锁定的话也是需要等待的。)

(4)即便在条件中使用了索引字段,但是否使用索引来检索数据是由MySQL 通过判断不同执行计划的代价来决定的,如果MySQL 认为全表扫描效率更高,比如对一些很小的表,它就不会使用索引,这种情况下InnoDB将使用表锁,而不是行锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值