4.mysql锁
锁
- 锁
- 锁是计算机协调多个进程或纯线程并发访问某一种资源的机制
- 锁冲突也是影响数据库并发访问性能的一个重要因素
- 锁的分类
-
页面锁(全局锁)
- 开销和加锁位于表锁和行锁之间,会出现死锁,锁定粒度界于表锁和行锁之间,并发一般
- 场景:全库逻辑备份,注意innodb由于有mvcc是支持备份的时候支持更新操作的
- 案例:
使用全局锁,执行之后整个数据库处于只读状态
flush tables with read lock
释放锁
unlock tables
-
表级锁
- 开销小,加锁快,不会出现死锁,锁定粒度大,发生锁冲突的概率最高,并发最低
- 表锁
表级别的共享锁,也就是读锁
lock tables t_student read
表级别的独占锁,也就是写锁
lock tables t_student write
释放锁
unlock tables
表锁除了会限制别的线程的读写外,也会限制本线程的读写操作 - 元数据锁(MDL)
- 不需要对显示的使用MDL,因为对数据库表进行操作的时候会自动给这个表加入MDL
- 对一张表进行CURD操作,加的MDL读锁(读读是不冲突的)
- 对一张表进行结构变更操作的时候,加的是MDL写锁
- MDL是在事务提交之后才会释放的,意味事务执行期间,MDL是一直持有的
- 申请MDL锁的操作会形成一个队列,队列中的写锁获取优先级高于读锁的,一旦出现MDL写锁等待,会阻塞后续该表的所有CRUD操作
- 不需要对显示的使用MDL,因为对数据库表进行操作的时候会自动给这个表加入MDL
- 意向锁
- 在使用innodb引擎时,对表里的某些记录加入【共享锁】之前,需要先在表级别加入【意向共享锁】
- 在使用innodb引擎时,对表里的某些记录加入【独占锁】之前,需要先在表级别加入【意向独占锁】
- 当执行插入、更新、删除操作时,需要先对表加上【意向独占锁】然后对记录加独占锁,而普通的select是不会加行级别锁的,select利用mvcc实现一致性读,是无锁的
select也是可以对记录加独占锁和共享锁的(锁定读)
先在表上加入意向共享锁,然后对读取的记录加入共享锁
select .... lock in share mode
先在表上加入意向独占锁,然后对读取的记录加入独占锁
select ... for update
这两条语句必须在一个事务中,因为当事务提交了,锁就会释放了 - 意向共享锁和意向独占锁是表级锁,不会和行级的共享锁和独占锁发生冲突,而且意向锁之间也不会发生冲突,只会和共享表锁(lock tables ... read)和独占表锁(lock tables ... write)冲突
- 表锁和行锁满足读读共享,读写互斥,写写互斥的
- 加入意向锁的目的是为了快速判断表里是否有记录被加锁
- Auto-Inc锁
- 假如说表主键字段设置了自增,之后插入数据可以不指定主键的值,会自动给主键赋自增的值。 这是由(auto-inc锁)来实现的
- Auto-Inc锁是特殊的表锁机制,不是再一个事务提交后才释放,而是执行完插入语句就立即释放
- 在插入数据时,会加一个表级别的Auto-Inc锁,然后被Auto_increment修饰字段赋值递增的值,等插入语句执行完成后,才会把Auto-Inc锁释放掉(mysql 5.1.22提供一种轻量化的锁(通过innodb_autoinc_lock_mode系统变量来控制)来实现自增,赋值自增的值就把锁释放了,不需要等待插入语句执行完成)
- innodb_autoinc_lock_mode
- 0 采取Auto-Inc锁,语句执行结束后才释放锁
- 2 采取轻量化锁,申请自增主键后就释放锁,并不需要等语句执行完成(性能最高,但当binlog日志格式是statment一起使用时,在主从复制会出现数据不一致的问题,可以使用binlog_format = row)
- 1 普通insert,自增锁在申请之后就马上释放,如果是批量插入,自增锁还是等语句执行完成
- 表锁
- 开销小,加锁快,不会出现死锁,锁定粒度大,发生锁冲突的概率最高,并发最低
-
行级锁
- 开销大,加锁慢,会出现死锁,锁定粒度最小,发生锁冲突的概率最低,并发最高。 (Innodb引擎是支持行锁的,myIsam是不支持的)
- 行锁的分类(3类)
- Record Lock 记录锁,也就是仅仅把一条记录锁上(锁住的是一条记录,在读已提交隔离级别下,行级别锁只有记录锁)
- Gap Lock 间隙锁,锁定一个范围,但是不包含记录本身
- Next-Key Lock(临键锁):Record Lock+ Gap Lock的组合,锁定一个范围,并锁定记录本身
- Record Lock锁
- Gap Lock锁(只存在于可重复读隔离级别,目的为了解决可重复读级别下幻读的现象)(间隙锁的X和S并不存在互斥关系)
- Next-Key Lock锁(包含了间隙锁和记录锁)
- 插入意向锁
- 插入意向锁虽然名字有意向锁,但它不是意向锁,它是一种特殊的间隙锁,属于行级别锁(间隙锁锁的是一个区间,而插入意向锁锁的是一个点)
- 一个事务在插入一条记录时,需要判断插入的位置是否被其他事务加入间隙锁,如果有的话就阻塞,直到拥有间隙锁提交为止,在此期间会生成一个插入意向锁,表明有事务想在此区间插入新纪录,但是现在是等待状态
- 插入意向锁和间隙锁的一个区别:尽管插入意向锁也属于间隙锁,但两个事务不能同一时间内,一个拥有间隙锁,另一个拥有该间隙锁区间的插入意向锁
-
链接:
-