mysql学习笔记-锁
1、MySQL并发事务访问相同记录
1.1 、读-读情况
读-读 情况,即并发事务相继 读取相同的记录。读取操作本身不会对记录有任何影响,并不会引起什么问题,所以允许这种情况的发生。
1.2 、写-写情况
写-写 情况,即并发事务相继对相同的记录做出改动。 所有隔离级别都解决了这种最严重问题。
1.3、读-写或写-读情况
读-写或 写-读,即一个事务进行读取操作,另一个进行改动操作。这种情况下可能发生 脏读 、 不可重复读 、 幻读 的问题
1.4 并发问题的解决方案。
方案一:读操作利用多版本并发控制(MVCC,下章讲解),写操作进行加锁。
方案二:读、写操作都采用 加锁 的方式。
2、不同角度锁的分类
2.1、从数据操作的类型划分:读锁、写锁
锁定读:
对读取的记录加 S锁:别的事务可以继续获取这些记录的S锁
对读取的记录加 X锁:其他事务既不能读也不能写
写操作:
DELETE :定位记录、获取记录X锁、执行delete mark操作
UPDATE:
①情况1:未修改该记录的键值,并且被更新的列占用的存储空间在修改前后未发生变化
则先在 B+ 树中定位到这条记录的位置,然后再获取一下记录的 X锁,最后在原记录的位置进行修改操作。我们也可以把这个定位待修改记录在 B+ 树中位置的过程看成是一个获取 X锁 的 锁定读。
②未修改该记录的键值,并且至少有一个被更新的列占用的存储空间在修改前后发生变化。
则先在 B+ 树中定位到这条记录的位置,然后获取记录的 X锁,将该记录彻底删除掉(就是把记录彻底移入垃圾链表),最后再插入一条新记录。这个定位待修改记录在B+树中位置的过程看成是一个获取X锁 的 锁定读 ,新插入的记录由 INSERT 操作提供的 隐式锁 进行保护。
③情况3:修改了该记录的键值,则相当于在原记录上做 DELETE 操作之后再来一次 INSERT操作,加锁操作就需要按照 DELETE 和 INSERT的规则进行了。
INSERT :
一般情况下,新插入一条记录的操作并不加锁,通过一种称之为 隐式锁 的结构来保护这条新插入的记录在本事务提交前不被别的事务访问。
2.2、从数据操作的粒度划分:表级锁、页级锁、行锁
① 表级别的S锁、X锁
某个表执行一些诸如 ALTER TABLE、 DROP TABLE这类的 DDL 语句,其他事务对这个表并发执行诸如SELECT、INSERT、DELETE、UPDATE的语句会发生阻塞。
②意向锁
如果我们给某一行数据加上了排它锁,数据库会自动给更大一级的空间,比如数据页或数据表加上意向锁,告诉其他人这个数据页或数据表已经有人上过排它锁了。
如果事务想要获得数据表中某些记录的共享锁,就需要在数据表上 添加意向共享锁。
如果事务想要获得数据表中某些记录的排他锁,就需要在数据表上添加意向排他锁。
③自增锁
AUTO-INC锁是当向使用含有AUTO_INCREMENT列的表中插入数据时需要获取的一种特殊的表级锁
事务在持有AUTO-INC锁的过程中,其他事务的插入语句都要被阻塞。
当我们向一个有AUTO_INCREMENT关键字的主键插入值的时候,每条语句都要对这个表锁进行竞争