谈谈你对Mysql 锁的理解
ysql 中的锁分类
- 按照粒度分表锁、行锁和页锁三种
- 按类型分为读锁和写锁(都属于悲观锁) 两种
- 按照性能分乐观锁、悲观锁、意向锁
其中,MyISAM和Memory 存储引擎采用的是表级锁,而innoDB存储引擎支持行级锁和表级锁
2. 表锁、行锁、页锁
表锁
每次操作锁住整张表。开销大,加锁快发生死锁的概率更小(多事务循环等待),锁粒度大,发生锁冲突的改概率最高,并发度最低,一般用在数据迁移的场景
CREATE TABLE locker(id INT PRIMARY KEY,name VARCHAR(255),value Int
);Insert into locker(id,name,value) VALUES (1,"MORAN",2),(2,"NIHAO",3).(3,"LISI",4)
BEGIN;
SELECT *FROM locker WHERE value =2 for update
因value字段没有索引,所以这个sql 语句对locker表进行加锁,也就是表锁,在事务提交之前,该表数据将无法被其他事务进行修改
行锁
对表中一行或多行记录仪进行加锁控制的方式。开销大、枷锁慢,会出现死锁 ,锁的粒度最小,发送锁冲突的概率最低,并发度最高,在Mysql中,行锁是基于索引加载的,即行锁是要加载索引响应的行上。索引失效就会升级为表锁
ALTER TABLE locker ADD index idx_value(value); -- 给locker表中的value 添加索引
BEGIN;
SELECT * FROM locker WHERE value =2 FOR UPDATE;
value 字段添加索引后,这条sql 只会针对value值为2的记录及逆行加锁,也就是行锁,在事务提交之前,这行数据将无法被其他事务及逆行修改
页锁
只有在BDB存储引擎支持页锁,页锁也就是在也的粒度上进行锁定,锁定的数据资源比行锁多,因为一个页中可以有多个行记录。当我们使用页锁的时候,会出现数据浪费的现象,但这样的浪费最多也就是在一个页上的数据行,页锁的开销介于表锁和行锁之间,会出现死锁,锁的粒度介于表锁和行锁之间。
3. 读锁、写锁、意向锁
读锁(共享锁,S锁(Shared))
多个读锁操作对同一个资源共享同一个锁 ,多个读锁操作可以同时进行而不会相互影响。因为读操作并不会改变数据内容,所以多个事务可以共享一个锁,并行地读取同一个资源,这样可以提高并发效率
写锁(排他锁,X锁(Exclude))
当两个事务同时对表中某行数据进行更新操作时,若一个事务先到达并给该行加上排他锁,那么另一个事务就不能在改行加任意类型的锁,直到第一个事务释放了该行的锁。因此,排他锁可以确保在同一时间只有一个事务可以对被加锁的资源进行修改操作,从而避免数据出现竞争和不一致的问题。
意向锁(I锁(Intent lock))
数据库中的一种表级锁,在行级锁的基础上引入的一种概念。意向锁适用于解决多粒度锁定而设计的,可以避免行级锁和表级锁之间的冲突。
意向锁分为两种类型:意向共享锁(Intention Shared Lock ,IS)和意向排他锁(Intention Exclusive lock,IX)
- 意向共享锁(IS):在一个事务需要对表中的某些行加共享锁(S锁)时,事务首先需要获得表的意向共享锁(IS 锁)
- 意向排他锁(IX) :指的是在一个事务需要对表中某些行加排他锁(X锁)时,事务首先需要获得表的意向排他锁(IX锁)
意向锁简单来说就是添加行锁时,给表添加一个标识表明该表已经存在共享锁或者是排他锁,其他事务需要加锁直接读取该标识判断是否已经存在锁