MySQL_锁机制
什么是锁?MySQL 中提供了几类锁?
锁是实现数据库并发控制的重要手段,可以保证数据库在多人同时操作时能够正常运行
排他锁(写锁),共享锁(读锁)
乐观锁,悲观锁
全局锁,表锁,行锁,页锁
什么是死锁?
死锁是指多个进程在执行过程中,因争夺资源而造成的互相等待的现象
如何处理死锁?
对待死锁常见的两种策略:
- 设置超时时间
- 发现死锁之后,主动回滚死锁中的某一个事务,让其它事务继续执行
如何避免死锁?
使用 SELECT … FOR UPDATE 语句来获取必要的锁
什么是全局锁?它的应用场景有哪些?
全局锁就是对整个数据库实例加锁,它的典型使用场景就是做全库逻辑备份
什么是共享锁?
共享锁又称读锁 ,是读取操作创建的锁
其他用户可以并发读取数据,但任何事务都不能对数据进行修改(获取数据上的排他锁),直到已释放所有共享锁
什么是排它锁?
排他锁,又称写锁
若某个事物对某一行加上了排他锁,只能这个事务对其进行读写,在此事务结束之前,其他事务不能对其进行加任何锁,其他进程可以读取,不能进行写操作,需等待其释放
使用全局锁会导致什么问题?
如果在主库备份,在备份期间不能更新,业务停摆,所以更新业务会处于等待状态
如果在从库备份,在备份期间不能执行主库同步的 binlog,导致主从延迟
悲观锁和乐观锁有什么区别?
- 悲观锁:每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁
- 共享锁和排它锁是悲观锁的不同的实现
- 乐观锁是用数据版本记录机制实现
乐观锁有什么优点和缺点?
因为没有加锁所以乐观锁的优点就是执行性能高
缺点就是有可能产生 ABA 的问题
ABA 问题指的是有一个变量 V 初次读取的时候是 A 值,并且在准备赋值的时候检查到它仍然是 A 值,会误以为没有被修改会正常的执行修改操作,实际上这段时间它的值可能被改了其他值,之后又改回为 A 值
⭐InnoDB 存储引擎有几种锁算法?
- Record Lock — 单个行记录上的锁
- Gap Lock — 间隙锁,锁定一个范围,不包括记录本身
- Next-Key Lock(包含行锁和间隙锁) — 锁定一个范围,包括记录本身
MyISAM 和 InnoDB 存储引擎使用的锁
- MyISAM 采用表级锁 (table-level locking)
- InnoDB 支持行级锁 (row-level locking) 和表级锁,默认为行级锁
表级锁和行级锁对比
- 表级锁: MySQL 中锁定 粒度最大 的一种锁,对当前操作的整张表加锁,实现简单,资源消耗少,加锁快,不会出现死锁。其锁定粒度最大,触发锁冲突的概率最高,并发度最低,MyISAM 和 InnoDB 引擎都支持表级锁
- 行级锁: MySQL 中锁定 粒度最小 的一种锁,只针对当前操作的行进行加锁。 行级锁能大大减少数据库操作的冲突。其加锁粒度最小,并发度高,但加锁的开销也最大,加锁慢,会出现死锁
优化锁方面你有什么建议?
- 尽量使用较低的隔离级别
- 尽量使用索引访问数据
- 选择合理的事务大小,小事务发生锁冲突的几率也更小
- 最好一次性请求足够级别的锁
- 尽量用相等条件访问数据,这样可以避免间隙锁对并发插入的影响
- 不要申请超过实际需要的锁级别
- 除非必须,查询时不要显示加锁
