0
点赞
收藏
分享

微信扫一扫

mysql中的悲观锁和乐观锁

醉倾城1 2022-11-18 阅读 50

悲观锁:获取数据时都会直接加锁,共享资源每次只给一个线程使用,其它线程阻塞等待。在数据库中提供了行锁、表锁等,操作数据时先加锁后使用。例如售票系统

select * from ticket where id=100 for update

乐观锁:不是数据库系统自带的,需要开发实现。乐观锁是只操作数据时并不进行任何特殊处理,也就是不加锁,在进行更新时才进行冲突判

锁模式

记录锁:在行相应的索引记录上的锁,锁定一个行记录 . 它会在 id=1 的记录上加上记录锁,以阻止其他事务插入,更新,删除 id=1 这一行。

gap 锁:间隙锁是封锁索引记录中的间隔,或者第一条索引记录之前的范围,又或者最后一 条索引记录之后的范围

临键锁 next-key 锁是记录锁与间隙锁的组合,它的封锁范围,既包含索引记录,又包含索引区间。

MYSQL8 RR 级别下默认使用临键锁 . 临键锁的主要目的,也是为了避免幻读 (Phantom Read) 。如果 把事务的隔离级别降级为RC ,临键锁则也会失效

意向锁:是为了支持多种粒度锁同时存在;

锁分类

全局锁:就对整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的 MDL DDL 语句、更

新操作的事务提交语句都将被阻塞。其典型的使用场景是做全库的逻辑备份,对所有的表进行锁

定,从而获取一致性视图,保证数据的完整性

        flush tables with read lock;

        unlock table

行级锁

        S 共享锁 :允许获取到此锁的事务读取行

        X 排他锁 :允许获取到此锁的事务 update delete

表级锁 - 意向锁

        表级锁会对当前操作的整张表加锁,最常使用的 MyISAM InnoDB 都支持表级锁定

        lock tables xxx read/write;

        IS 意向共享锁:事务打算对表中的行设置共享 S

        IX 意向排他锁:事务打算对表中的行设置排他 X

        意向锁是 InnoDB 自动加的, 不需用户干预

意向锁定协议

        事务在获得表中某行上的共享锁之前,必须先获得表上的IS 锁或更高级别的锁

        在事务可以获得表中某一行上的排他锁之前,它必须首先获得表上的IX

按加锁方式分类

按加锁方式划分,可分为自动锁、显示锁。

隐式加锁:

        InnoDB自动加意向锁

        对于UPDATE DELETE INSERT 语句, InnoDB 会自动给涉及数据集加排他锁

        对于普通SELECT 语句, InnoDB 不会加任何锁;

        随时都可以执行锁定,InnoDB 会根据隔离级别在需要的时候自动加锁;锁只有在执行commit或者rollback 的时候才会释放,并且所有的锁都是在同一时刻被释放。

显式加锁:

        共享锁S SELECT * FROM table_name WHERE … LOCK IN SHARE MODE

        排他锁X SELECT * FROM table_name WHERE … FOR UPDATE

按照算法分类

按照算法分类,可分为间隙锁、临键锁、记录锁。

间隙锁:间隙锁基于非唯一索引,它锁定一段范围内的索引记录。使用间隙锁锁住的是一个区间,

而不仅仅是这个区间中的每一条数据。 select * from tb_users where id between 1 and 10

for update ; 即所有在(

1 10 )区间内的记录行都会被锁住,所有 id 2 3 4 5 6 7 8

9 的数据行的插入会被阻塞,但是 1 10 两条记录行并不会被锁住

临键锁是记录锁与间隙锁的组合,它的封锁范围,既包含索引记录,又包含索引区间,是一个左开

右闭区间。临键锁的主要目的,也是为了避免幻读 Phantom Read 。如果把事务的隔离级别降级为

RC ,临键锁则也会失效。每个数据行上的非唯一索引列上都会存在一把临键锁,当某个事务持有该

数据行的临键锁时,会锁住一段左开右闭区间的数据。需要强调的一点是, InnoDB 中行级锁是基

于索引实现的,临键锁只与非唯一索引列有关,在唯一索引列(包括主键列)上不存在临键锁。

记录锁是封锁记录,记录锁也叫行锁,如 select *from tb_users where id=1 for update ;

会在 id=1 的记录上加上记录锁,以阻止其他事务插入,更新,删除 id=1 这一行。

相关锁总结

记录锁、间隙锁、临键锁,都属于排它锁

记录锁就是锁住一行记录

间隙锁只有在事务隔离级别 RR 可重复读 中才会产生

        唯一索引只有锁住多条记录或者一条不存在的记录的时候,才会产生间隙锁,指定给某条存在的记录加锁的时候,只会加记录锁,不会产生间隙锁

        普通索引不管是锁住单条,还是多条记录,都会产生间隙锁

        间隙锁会封锁该条记录相邻两个键之间的空白区域,防止其它事务在这个区域内插入、修改、删除数据,这是为了防止出现幻读现象

普通索引的间隙,优先以普通索引排序,然后再根据主键索引排序

事务级别是 RC 读已提交级别的话,间隙锁将会失效

表级锁: 开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高 , 并发度最低。

行级锁: 开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低 , 并发度也最高。

页面锁: 开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度

举报

相关推荐

0 条评论