加入收藏 | 设为首页 | 会员中心 | 我要投稿 常州站长网 (https://www.0519zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

Mysql中锁的使用场景介绍

发布时间:2023-12-31 22:41:54 所属栏目:MySql教程 来源:DaWei
导读: 这篇文章主要讲解了“Mysql中锁的使用场景是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Mysql中锁的使用场景是
这篇文章主要讲解了“Mysql中锁的使用场景是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Mysql中锁的使用场景是什么”吧!

一、常见锁类型
表级锁,锁定整张表
页级锁,锁定一页
行级锁,锁定一行
共享锁,也叫S锁,在MyISAM中也叫读锁
排他锁,也叫X锁,在MyISAM中也叫写锁
悲观锁,抽象性质,其实不真实存在
乐观锁,抽象性质,其实不真实存在

二、Mysql引擎介绍
其实mysql中的引擎有很多种类,其中InnoDB和MyISAM引擎最常用
在mysql5.5版本前默认使用MyISAM引擎,之后使用InnoDB引擎
查看数据库引擎命令如下
show variables like '%storage_engine%';

三、常用引擎间的区别
MyISAM 操作数据都是使用的表锁,你更新一条记录就要锁整个表,导致性能较低,并发不高。当然同时它也不会存在死锁问题。
而 InnoDB 与 MyISAM 的最大不同有两点:一是 InnoDB 支持事务;二是 InnoDB 采用了行级锁。
在 Mysql 中,行级锁并不是直接锁记录,而是锁索引。索引分为主键索引和非主键索引两种,如果一条sql 语句操作了主键索引,Mysql 就会锁定这条主键索引;如果一条语句操作了非主键索引,MySQL会先锁定该非主键索引,再锁定相关的主键索引。
InnoDB 行锁是通过给索引项加锁实现的,如果没有索引,InnoDB 会通过隐藏的聚簇索引来对记录加锁。也就是说:如果不通过索引条件检索数据,那么InnoDB将对表中所有数据加锁,实际效果跟表锁一样。因为没有了索引,找到某一条记录就得扫描全表,要扫描全表,就得锁定表。

四、共享锁与排他锁
数据库的增删改操作默认都会加排他锁,而查询不会加任何锁。
共享锁:对某一资源加共享锁,自身可以读该资源,其他人也可以读该资源(也可以再继续加共享锁,即 共享锁可多个共存),但无法修改。要想修改就必须等所有共享锁都释放完之后。
排他锁:对某一资源加排他锁,自身可以进行增删改查,其他人无法进行任何操作。
//共享锁
select * from 表名 lock in share mode

//排他锁
select * from 表名 for update

五、排他锁的实际应用
这里我们以两个操作数据库的请求为例,假设这两个请求分别为T1和T2
假设T1为查询请求,而T2为更新数据请求,在T1查询很长时间的时候,还没有返回结果,但是这时候T2过来请求更新了
这个流程应该是: T1运行加共享锁、T2运行、发现T1未完成等待其完成、T1完成、T2开始执行
T2之所以要等待,是因为T2执行更新的时候需要给表加排他锁,但是数据库规定,不能在同一资源上同时共存这两种锁,所以T2必须等T1执行完,释放锁后,才可以正常操作
T1: select * from 表名 lock in share mode //假设还未返回结果
T2: update 表名 set name='autofelix'

六、共享锁的实际应用
如果T1和T2都是执行的查询,也就是都加共享锁
这时候就不用等待,可以立马执行
因为同一资源上可以同时存在多个共享锁,也被称为,共享锁与共享锁兼容
意味着共享锁不阻止其他人同时读取资源,但是阻止其他人修改资源
T1: select * from table lock in share mode
T2: select * from table lock in share mode

七、死锁的发生
假设T1和T2都同时执行2个资源操作,分别是查询和更新数据
假设T1和T2同时达到select,T1对表加共享锁,而T2也加上了共享锁
当T1的select执行完毕,准备执行update时
根据锁机制,T1的共享锁必须升级到排他锁才可以执行接下来的update操作
在升级排他锁之前,必须等T2的共享锁释放,同理,T2也在等T1的共享锁释放
于是都在等待对方的锁释放,导致程序卡死,这种情况就是死锁
T1: 开启事务,执行查询更新两个操作

     select * from table lock in share mode

     update table set column1='hello'

T2: 开启事务,执行查询更新两个操作

     select * from table lock in share mode

     update table set column1='world'

八、另一种发生死锁的情景
当T1和T2都是只执行更新语句的时候
如下程序所示,这种语句非常的常见,很多人觉得他会产生死锁,其实要看情况
如果id是主键,由于主键机制,并不需要全表扫描,直接可以更新当前数据,所以不会产生死锁
如果id是普通字段,那么当T1加上排他锁之后,T2为了找到id=20条数据,必须进行全表扫描,当他扫到第10条的时候,发现这里有排他锁,导致全表扫描进行不下去,就会导致等待
T1: begin
     update table set content='hello' where id=10

T2: begin
     update table set content='world' where id=20

九、死锁的解决方式
就是让T1和T2顺序执行,比如T1在执行完select后,立马给自身加上排他锁,这样T2不得不等待T1执行完才能继续
但是如果有很多请求过来的话,都必须等待,这对用户特别的不友好
所以,某些数据库引入了另一种方式,叫做更新锁,这里mysql除外,不存在更新锁
更新锁其实就是排他锁的另一种实现,只是他允许其他人读的同时加共享锁,但是不允许其他操作,除非释放了更新锁
流程大概如此: T1执行完select加上更新锁,T2执行查询完,准备加更新锁,发现已经有了,就等待,其他请求过来,如果查询是不受影响的,但是更新才等待
这相比上面的查询也要等待增加了效率
T1: begin

     select * from table for update

     update table set content='hello'

T2: begin

     select * from table for update

     update table set content='world'
复制代码
T1: begin

     select * from table [加更新锁操作]

     update table set content='hello'

T2: begin

     select * from table [加更新锁操作]

     update table set content='world'

感谢各位的阅读,以上就是“Mysql中锁的使用场景是什么”的内容了,经过本文的学习后,相信大家对Mysql中锁的使用场景是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。

(编辑:常州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章