MySQL 锁机制
数据库锁:
概念:
锁是计算机协调多个进程或线程并发访问某一资源的机制(避免资源争抢)
分类:
按粒度
- 表级锁:锁定整个表
开销小 加锁快 不会出现死锁
锁定粒度大 发生锁冲突的概率最高 并发度最低
数据库引擎总是一次性同时获取所有需要的锁以及总是按相同的顺序获取表锁从而避免死锁
表读锁 会阻塞写 不阻塞读
表写锁 读写都阻塞- 元数据锁:可以理解为表结构锁 对表的结构进行加锁
表在做增删改查动作的时候 加读锁
表在修改结构的时候 加写锁
- 页面锁:只有BDB引擎支持
- 开销和加锁时间界于表锁和行锁之间
会出现死锁
- 锁定粒度界于表锁和行锁之间,并发度一般。
- 行级锁:锁定当前操作行 只有InnoDB支持
开销大 加锁慢 会出现死锁
锁定粒度最小 并发度也最高
行锁是逐步获得的 因此会出现死锁- 行锁并不是锁行数据 而是锁索引(主索引、二级索引)在更新、删除的时候还会锁定相邻的键值
- 全局锁:对整个数据库实例加锁 数据库变成只读状态
最多是在数据备份时使用
InnoDB引擎支持表锁和行锁 默认采用行锁
按读写
- 排它锁:又称独占锁、X锁、写锁
X锁不能和其他锁兼容,只要有事务对数据上加了任何锁,其他事务就不能对这些数据再放置X了,同时某个事务放置了X锁之后,其他事务就不能再加其他任何锁了,只有获取排他锁的事务是可以对数据进行读取和修改
。 - 共享锁:又称读锁、S锁
S锁与S锁兼容 可以同时放置
- 更新锁:又称U锁
它允许再加S锁,但不允许其他事务再施加U锁或X锁,当被读取的数据要被更新时,则升级S锁为X锁。U锁的优点是允许事务A读取数据的同时不阻塞其它事务,并同时确保事务A自从上次读取数据后数据没有被更改,因此可以减少X锁和S锁的冲突,同时避免使用S锁后再升级为X锁造成的死锁现象。注意,MySQL并不支持U锁,SQLServer才支持U锁
。
按状态:
当行锁锁定后 会自动为当前表添加意向锁
意向锁分为:意向共享锁、意向排他锁 类型由行锁类型决定
意向锁的作用就是 在申请表锁的时候 不需要一行行判断是否有行锁
只需要判断当前表是否有意向锁就行
按算法:
下面三种所都是行锁
- 记录锁:锁住一行记录 也分读写锁
- 间隙锁:锁住一段范围 是为了解决可重复读级别下的幻读问题
- 临键锁:相当于记录锁和间隙锁的结合 能锁住一定范围和一行记录
死锁:
间隙锁是相互兼容的 所以可能存在两个事务对同一段间隙都加锁的情况
然后都在等待对方释放间隙锁
解决死锁:
- 设置事务等待锁的超时时间:事务的等待时间超时后 主动回滚事务
InnoDB中是参数:innodb_lock_wait_timeout 默认值为50秒 - 开启主动死锁检测:在发现死锁后 主动回滚某一个事务
InnoDB中是参数:innodb_deadlock_detect 默认是on 表示开启