MySQL锁机制(笔记)

一.全局锁介绍

2.如果在锁:
我们要去备份这三张表的数据的时候,我们的业务系统还在对这个数据库操作数据; 

备份的时候一个表一个表的备份;
假如库存表正在备份的时候,正好有人下单,那么此时库存减一,紧接着生成订单,插入数据,然后插入订单日志。
此时库存还是原来的库存没有扣减。拿到的这份数据已经插入了订单,和订单日志

3.语法
Flush(先加全局锁),逻辑备份之前
mysqldunmp,执行数据备份 itcast指的是哪个数据库,itcast.sql(存到哪个数据库当中)
unlock(释放全局锁),逻辑备份之后

4.全局锁_一致性数据备份

备份使用mysqldump工具..
使用全局锁可以实现数据备份可以保证一致性和完整性..但粒度很大!
备份期间所有客户端不能执行写入操作

二、表级锁介绍

2.表级锁的分类:

表级锁_表锁的分类:

    - 表共享读锁(read lock):读锁(read)
    - 表独占写锁(wirte loc k):写锁  (write)

共享读锁的特点:
假设客户端1在这里加了一个读锁,那么锁住了之后,就可以读取数据,但是不能执行写入操作
客户端2也是一样
当释放掉就可以正常操作

当前加锁的客户端自己也不可以写!!!别的客户端执行写操作会进入阻塞!!

客户端一二无法进行写操作

当客户端一释放掉的时候,客户端二执行了写操作

独占写锁的特点:
假设客户端1加了写锁,加了写锁,其他客户端不能读也不能写,我当前客户端既能操作写也能读

当前加锁的客户端可以读,可以写.别的客户端不可以读,不可以写!会进入阻塞状态,等待加锁的客户端来解锁!

客户端二一直阻塞

当客户端一释放

客户端二开始执行查询操作

总结:

表级锁_

元数据<==>表结构<==>DDL(元数据可以简单地理解为表结构)

 就是当还在执行事务的时候,还未提交事务,我们无法修改表的结构

 SHARED_READSHARED_WRITE共享锁之间是兼容的!
 但是一旦碰到EXCLUSIVE排他锁,就会进入阻塞!

演示:

两边执行select查询的时候就会自动加上元数据锁,兼容,我们可以查得到下图

此时我们在客户端二执行写操作的时候(DML也是能够执行的),当我们执行select,以及update语句的时候都会去加上对应的元数据锁,这两类都是共享锁,都是兼容的

如果再执行alter的话,那么就会处于阻塞:

客户端一,开启事务并执行查询语句

客户端二开启事务,修改表的结构,结果:此时客户端二处于阻塞状态,因为我们客户端一在执行查询语句的时候自动加上SHARE_READE(共享读锁)
那么客户端二执行alert语句的时候,我们是加上排他锁,这个锁与其他的锁都是互斥的,所以导致处于客户端阻塞状态
得等到客户端一提交了事务后,才会去执行alter语句

理解:
在a事务中select语句会给表加上元数据读锁,事务b中insert update delete会加上元数据写锁.但是这种读锁和写锁是兼容的!
但是在别的事务中执行alter等语句时,会加'排他锁',这个锁和读锁还有写锁是排斥的.
所以如果当前有别的事务没提交,当前alter语句会被阻塞!

metadata_lock

表级锁_意向锁

线程A:开启事务,然后执行update语句,默认隔离级别根据主键更新默认加上行锁

线程B:想要直接锁表(加锁)(读锁或者写锁),加上可能导致表锁和行锁产生冲突,那么当它去锁表(执行sql)的时候,先去判断这张表有没有加行锁以及根据行锁的类型确定看能不能加锁成功(第一条记录开始检查有没有加行锁,什么类型的行锁,检查到最后一行

要想加上表锁,就必须一行一行检查,性能极低
所以引入意向锁(解决在执行DML语句的行锁以及表锁的冲入突
使用意向锁来减少表锁的检查,提高性能

意向锁:
线程A:照样步骤,在执行update的语句先加上这行的行锁随之整张表加上意向锁
线程B:  要来加上表锁,先检查这张表意向锁的情况,通过意向锁的情况来判断能不能加锁成功,如果能够兼容就加上表锁,否则处于阻塞状态,等待线程A事务提交,释放掉行锁,意向锁,随之接触阻塞状态,拿到表锁
引入意向锁无需逐行检查行锁情况,只需根据意向锁的类型以及情况来添加

过程:
之前是事务要加表锁的时候需要逐行检查当前表中是否有行锁,以避免所冲突,但效率太低.
引入了意向锁后,别的事务加表锁的时候就不需要进行逐行检查是否加行锁了.直接根据加行锁时给表也加的
意向锁的类型和兼容性来决定,是否可以加表锁.

IS:
IX:

意向锁的兼容情况:


演示:

意向共享锁与表锁的兼容情况:

(1)事务a

(2)事务b

意向排他锁和表锁的兼容情况:

(1)事务a中:

(2)事务b中:

演示二:

线程A:

线程B:
加表锁的时候会去先判断这张表意向锁的情况

加读锁(read):成功

加上写锁:处于阻塞状态

提交事务
成功锁住

此时线程A锁释放

---------------------------------------------------------------------------------------------------------------------

线程A:


线程B:
读锁阻塞

加写锁,写锁也阻塞


提交事务,
线程A释放,
线程B成功锁住

三、行级锁

每次锁的是行数据,粒度最小.发生锁冲突最低.并发性最高.只支持InnoDB
InnoDB存储引擎的数据是基于索引组织形成的,行锁是对索引上的索引项加锁实现的.而不是对记录加的锁.

对索引项ID为34的记录加上行级锁

总结:

间隙锁的唯一目的就是防止其他事务插入间隙,造成幻读现象!
(对于唯一索引来说,约束就会限制住重复数据出现,所以直接就避免幻读)

注意:

兼容情况:

注意: 根据唯一索引select 和 根据普通索引select,加锁的情况是不一样的!!!

默认情况下,InnoDB会在RR隔离级别下,用临键锁来搜索,检索...防止幻读..(RC中只有行锁,没有间隙锁)

记住这里是通过唯一索引(技巧)

select * from city where id = ?    lock in ...                ====>        会对行记录加上共享读锁,且为表加上意向共享锁

客户二正常执行sql查询语句id=1

客户端一

那么客户端二查询是否存在锁 S(共享锁),REC_NOT_GAP(无间隙)

同时客户端二执行同样操作

当事务提交时,锁被释放

--------------------------------------------------------------

共享锁与排他锁互不兼容,针对行级记住,不要与前面学的锁搞混

排他锁与排他锁是否存在相互兼容????

客户端一:开启事务执行修改操作(DML),开启了排他锁

客户端二:开启事务执行同样的操作

结果:一直处于阻塞状态,必须等待左侧客户端一释放掉排他锁

排他锁与排他锁之间是相互排斥(两个窗口同时对ID为2的用户执行修改操作)

牢记:

客户端一:name没有加索引,全表的记录加锁(表锁)

客户端二:

注意:如果给name建索引的话,此时两个客户端之间不会互相影响

客户端一:update ... where id = 5;  此时存在的记录是id 3, 8. 于是会给(3, 8)开区间加间隙锁(锁住的是3和8之间的间隙)(防止幻读)  +  意向排他锁

客户端二:

此时处于阻塞状态,必须得等客户端一提交事务

间隙锁的唯一目的就是防止其他事务插入间隙,造成幻读现象(多个事务并发问题)!

(对于唯一索引来说,约束就会限制住重复数据出现,所以直接就避免幻读)

假设表中有索引列 id,现有数据 id = 1id = 3

  • 事务 A 执行 SELECT * FROM table WHERE id BETWEEN 1 AND 3 FOR UPDATE;
  • 此时,间隙锁会锁定 (1,3) 这个间隙(即不包含 1 和 3 的区间),防止其他事务插入 id=2
  • 若其他事务尝试插入 id=2,会被阻塞,直到事务 A 提交或回滚。

重点:

在唯一索引下的等值匹配,给已存在的记录加锁.临键锁会优化为行级锁,因为唯一性约束就直接避免了幻读.因为当前记录就不允许重复插入,所以避免了幻读.

 在唯一索引下的等值匹配,给不存在的记录加锁.会优化为间隙锁,避免别的事务在当前不存在的记录的这个间隙之间插入数据!避免了幻读的问题!

非唯一索引下的等值匹配,给存在的记录加锁.会加三把锁: 当前记录 + 当前记录之前的间隙 + 当前记录之后的间隙

为什么要锁间隙呢?? 因为防止别的事务在当前间隙下插入数据造成幻读现象

InnoDB下RR隔离级别下,默认采用临键锁来对数据进行检索.在不同场景下,有不同的优化.来防止幻读.    

总之有的是因为唯一约束间接避免了幻读, 其他(非唯一)都是通过要加间隙的方式防止别的事务进行插入数据!

为什么不走索引/索引失效会造成表锁升级为行锁?
-
加锁是对索引项加锁,而不是记录本身.所以不走索引的话,需要全表扫描,那就只能对表加锁了!
- 注意,RC隔离级别下不会表升级.只有RR才会.RC下只有行级锁...

如何选择RC和RR?

1)RC的虽然可能对数据的一致性会低一些,但是RC这种隔离级别的性能是很高的(多条读是不需要加事务的).对性能并发更好一些...

(2)如果是比如希望做一些报表,要求数据一致性要求比较高.且对性能要求没那么高,选择RR.
MVCC(快照读)  +  锁机制(当前读)阐述:
         锁机制方面: 行级锁  间隙锁  临键锁(左闭右开)
          RC仅仅支持行级锁,因为它允许发生不可重复读和幻读
          RR不仅支持行级锁,还支持间隙锁 + 临键锁的方式来解决幻读问题。所以更可能发生死锁问题

  条件列未使用到索引,RR锁表(select也会),RC锁行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值