目录
就问你锁恶不恶心人
锁在程序员的世界里无处不在,因为并发无处不在
锁住共享资源,防止并发造成的问题
从Java锁到数据库锁,悲观锁、乐观锁,行锁、表锁,读锁、写锁,自旋锁,可重入锁,CAS,死锁,分布式锁等等等。。。
我是觉得锁这一大块很难啃,上面每一个点都需要花很多时间学习了解和思考
本篇主要初步探索mysql锁
全局锁
对整个数据库实例加锁
使整个库处于只读状态
flush tables with read lock
一般不怎么用,很少用到,个人觉得,开发了解即可,就算用到也是dba用吧估计
使用场景:
做全库逻辑备份,也就是把整个库的所有表都select出来存成文本
表级锁
表锁:
lock tables 表名 read/write;
unlock tables (主动释放锁);
元数据锁(meta data lock,MDL):
也称为字典锁
字典锁是为了保护数据对象被改变,一般是一些DDL会对字典对象改变,如两个事务,事务1先查询表,然后事务2试图alter,其首先需要等待事务1结束(提交或回滚),此时的状态便是Waiting for table metadata lock,然后才能获得字典锁。如果是线上业务的核心表出现了这样的锁等待队列,就会造成灾难性的后果。字典锁与数据锁相对应。数据锁是保护表中的数据,如两个事物同时更新一行时,先得到row lock的事务会先执行,后者只能等待。
详见 https://blog.51cto.com/277963679/1976802
页锁
行锁
这一部分是我们需要关注的重点
Myisam是表锁,不支持行锁
mysql默认存储引擎Innodb支持行锁,因此我们重点关注Innodb的行锁即可
顾名思义,行锁就是锁住某些行,锁的力度更细,比表锁的并发性更好,表锁一锁就锁整张表
注意:在innodb事务中,行锁是在需要的时候才加上的。但并不是不需要了就立即释放,而是等到事务结束才释放。【两阶段锁协议】
误解:Innodb有行锁也有表锁,不是Innodb只有行锁
select for update 详述
MVCC
(Multi-Version Concurrency Control)多版本并发控制
锁具表中的一行记录,可能有多个版本,每个版本都有自己的row_trx_id(按申请顺序严格递增)
对数据库的任何修改的提交都不会直接覆盖之前的数据,而是产生一个新的版本与老版本共存,使得读取时可以完全不加锁。
Information_schema
在Information_schema有三个和锁相关的表INNODB_TRX,INNODB_LOCKS,INNODB_LOCK_WAITS
SELECT * from information_schema.INNODB_TRX;
详见 https://www.jianshu.com/p/f2906978f283
意向锁
为了允许行锁和表锁共存,实现多粒度锁机制,
InnoDB还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁:
- 意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
- 意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。
意向锁数据库隐式帮我们做了
间隙锁
只会在Repeatable read隔离级别下使用
Repeatable read隔离级别下再通过GAP锁即可避免了幻读
举个例子:
小明,小红,小花三个人依次站成一排(小明和小红是情侣,小红和小花是闺蜜)
如何让新来的小刚不能站在小红旁边,这时候只要将小红和她前面的小明之间的空隙封锁,将小红和她后面的小花之间的空隙封锁,那么小刚就不能站到小红的旁边。
这里的小红,小明,小花,小刚就是数据库的一条条记录。
他们之间的空隙也就是间隙,而封锁他们之间距离的锁,叫做间隙锁。
````
session 1:
start transaction ;
select * from news where number=5 for update;
session 2:
start transaction ;
insert into news value(4,4);#(阻塞)
insert into news value(4,5);#(阻塞)
insert into news value(5,5);#(阻塞)
insert into news value(7,11);#(阻塞)
insert into news value(9,12);#(执行成功)
insert into news value(12,11);#(阻塞)
update news set number=5 where id=1;#(阻塞)
update news set id=11 where number=11;#(阻塞)
update news set id=2 where number=4 ;#(执行成功)
update news set id=4 where number=4 ;#(阻塞)
````
检索条件number=5,向左取得最靠近的值4作为左区间,向右取得11为右区间,因此,session 1的间隙锁的范围(4,5),(5,11)
锁定的意思是不得在(3,4)、(6,5)、(8,5)、(10,5)、(13,11)插入新值
摘自下面这篇文章,感受下大佬对间隙锁详细的分析和案例:
https://www.cnblogs.com/crazylqy/p/7821481.html
如有任何问题敬请指正
彩蛋
阿里本地生活双十一燥起来=-=
恭喜fpx这五个分奴夺得冠军
super carry doinb
转载请注明:汪明鑫的个人博客 » mysql不得不学的恶心锁事 概念篇
说点什么
您将是第一位评论人!