美文网首页
mysql 的S 锁和X锁的区别

mysql 的S 锁和X锁的区别

作者: 滨岩 | 来源:发表于2020-03-05 10:24 被阅读0次

Mysql的锁系统

Shared lock 和 exclusive lock(共享锁和排它锁,也就是读锁和写锁,即read lock 和write lock)

读锁是共享的,或者说是相互不阻塞的,
写锁是排他的,一个写锁会阻塞其他写锁和读锁

共享锁(shared lock S锁)

如果事务T1对数据对象A加上S锁,则事务T可以读A但是不能修改A,其他事务T2只能再对A加S锁,而不是X锁,一直持续到T1释放A上的S锁。

排他锁(exclusive lock X锁)

如果事务T1对数据对象A加上X锁,则事务T可以读取A也可以修改A,其他事务T2不能对该对象加任何锁,一直持续到T释放A上的锁。保证了其他事务在T1释放A上的锁之前不能读取或修改对象A

image.png

锁的粒度和锁的策略

MySQL有三种锁的级别:页级、表级、行级。
MyISAM 和MEMORY存储引擎采用的是表级锁(table-level locking);
BDB 存储引擎采用的是页面锁(page-level locking),但也支持表级锁;
InnoDB存储引擎既支持行级锁(row-level locking) ,也支持表级锁,但默认情况下是采用行级锁。

MySQL 这3中锁的特性可大致归纳如下:
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低;
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最小,并发度最高;
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

脏读、不可重复读、幻读

脏读:事务A读取了事务B未提交的记录;如果事务B在修改这条记录的时候加了X锁,则事务A就无法读取该条记录了,也就不会出现脏读;

不可重复读:事务A先读取该条记录,但是事务B对该条记录做了改动并提交之后,事务A再次读取记录时,就会获取到不同的值。解决方法是事务A读取该记录时,对该记录加S锁,事务B就无法修改记录,然后不会发生不可重复读。

幻读:当前事务A读取了一个范围的记录,然后另外的事务B向该范围插入了新记录,当前事务A再次读取该范围的记录时,发现了新插入的新记录,我们把新插入的那些记录称之为“幻影记录”。在一次事务里面,多次查询之后,结果集的个数不一致的情况叫做幻读。而多或者少的那一行被叫做 幻行

如何解决幻读

1、多版本并发控制(MVCC) (快照读/一致性读)

多数数据库实现了多版本并发控制,并且都是靠保护数据快照实现的。
InnoDB 每一行记录都冗余了两个字段,一个是行的创建版本,一个行的删除(过期)版本。
具体的版本号(trx_id)存在information_schema.INNODB_TRX表中。
版本号(trx_id)随着每次事务开启自增。事务每次读取数据时候,都会创建版本小于当前事务版本的数据,以及过期版本大于当前版本的数据。
普通的select就是快照读。
select * from table where id=100;
原理:将历史数据存一份快照,所以其他事务增加和删除数据,对于当前事务来说是不可见的。

2. next-key 锁 (当前读)

next-key 锁包含两部分 记录锁(行锁) 间隙锁(gap锁)

当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁

对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”,InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁(next-Key锁)【行锁+gap锁】

记录锁是加在索引上的锁,间隙锁是加在索引之间的。(思考:如果列上没有索引会发生什么?)

select * from account where account_id= 1 for update;
select * from account where account_id = 1 lock in share mode;
insert
update
delete
原理:将当前数据行与上一条数据和下一条数据之间的间隙锁定,保证此范围内读取的数据是一致的。

实例:

假如emp表中只有101条记录,其empid的值分别是 1,2,...,100,101,下面的SQL:

mysql> select * from emp where empid > 100 for update;

是一个范围条件的检索,InnoDB不仅会对符合条件的empid值为101的记录加锁,也会对empid大于101(这些记录并不存在)的“间隙”加锁。(如果where条件全部命中,则只会添加记录锁,如果部分命中或者全部命中,则会加Gap锁)

InnoDB使用间隙锁的目的:

1.防止幻读,以满足相关隔离级别的要求。对于上面的例子,要是不使用间隙锁,如果其他事务插入了empid大于100的任何记录,那么本事务如果再次执行上述语句,就会发生幻读;

2.为了满足其恢复和复制的需要。

相关文章

  • mysql X锁和S锁

    mysql X锁和S锁基本的封锁类型有两种: 排它锁(X锁)和共享锁(S锁): 所谓X锁,是事务T对数据A加上X锁...

  • mysql 的S 锁和X锁的区别

    Mysql的锁系统 Shared lock 和 exclusive lock(共享锁和排它锁,也就是读锁和写锁,即...

  • 你应该知道的

    本次更新:20180319一、Mysql:1.S锁(共享锁)、X锁(排它锁):select语句默认加S锁;2.聚簇...

  • 2019-07-23工作总结

    疑问1: MDL写锁, MDL读锁, 和S锁, X锁有啥区别? 疑问2: flush文件有啥作用? 答: fl...

  • Mysql X锁,S锁、间隙锁

    1,Mysql X锁和S锁。 1)概念:利用数据库本身提供的锁机制(行级锁)来实现,锁定该行数据。trx_rows...

  • MySQL的锁与事务

    MyISAM和InnoDB锁区别 MyISAM默认行级锁,不支持表级锁InnoDB都支持这里我们假设X为排他锁,S...

  • MySQL-InnoDB行锁

    InnoDB的锁类型 InnoDB存储引擎支持行锁,锁类型有两种: 共享锁(S锁) 排他锁(X锁) S和S不互斥,...

  • 三级封锁协议

    锁的类型:基本的封锁类型有两种:排它锁(X锁)和共享锁(S锁)X锁,是事务T对数据A加上X锁时,只允许事务T读取和...

  • 蚂蚁面试

    1、mysql乐观锁和悲观锁的区别? 乐观锁通过MVCC,版本实现,悲观锁select... for update...

  • 无法复现的“慢”SQL《死磕MySQL系列 八》

    系列文章 四、S 锁与 X 锁的爱恨情仇《死磕MySQL系列 四》[http://mp.weixin.qq.com...

网友评论

      本文标题:mysql 的S 锁和X锁的区别

      本文链接:https://www.haomeiwen.com/subject/fzftrhtx.html