MySql数据库中的锁机制

数据库中的锁机制

数据库中的锁机制是默认在内部运行的机制。使用者是了解这一机制,更好的支持后续的操作。

从效率的角度考虑:

1. 2个事务并发访问同一张表,2个都做查询,没必要互斥
2. 2个事务并发访问同一张表,1个查询,1个更新,是否有必要互斥,看具体应用场景

	例子1:共享单车站点可用车查询-没必要互斥
	例子2:秒杀-有必要互斥

3. 2个事务并发访问同一张表,2个都执行更新操作,有必要互斥的

数据库的设计者设计了两种锁+不加锁的操作,来实现上述场景的效率和安全的保证。

不加锁的操作:和任何的锁都不互斥
共享锁(读锁):所有加共享锁的操作彼此之间不互斥
排他锁(写锁):和所有的加锁操作有互斥

非Serlizable级别:查询不加任何锁
Serlizable级别:查询加共享锁
所有的级别下:更新(增删改)加排他锁

A(非Ser)		B(非Ser)		是否互斥		原因
读			读			不互斥		A和B都不加锁
读			写			不互斥		A不加锁 B排他锁
写			读			不互斥		A排他锁 B不加锁
写			写			互斥			A排他锁 B排他锁

A(Ser)		B(非Ser)		是否互斥		原因
读			读			不互斥		A共享锁 B不加锁
写			读			不互斥		A排他锁 B不加锁
读			写			互斥			A共享锁 B排他锁
写			写			互斥			A排他锁 B排他锁

A(Ser)		B(Ser)		是否互斥		原因
读			读			不互斥		A共享锁 B共享锁
写			读			互斥			A排他锁 B共享锁
读			写			互斥			A共享锁 B排他锁
写			写			互斥			A排他锁 B排他锁

在这里插入图片描述

小问题:基于上述规则,2个事务并发访问时,是否会出现死锁的情况?

在这里插入图片描述

更新丢失

并发的2个事务基于同一个查询结果对数据库进行更新操作,后提交的事务忽略了先提交的事务对数据库造成的影响,因此造成的问题称为“更新丢失”。

更新丢失的解决方案:

数据库如果使用Serializable级别,可以天然防止更新丢失,但是对业务的执行效率会有较大的影响。

悲观锁解决方案:悲观锁悲观的认为,查询就可能造成更新丢失。因此,在查询时手动添加共享锁或者排他锁(推荐),以此解决更新丢失的问题。

乐观锁解决方案:乐观锁乐观的认为,查询不会造成更新丢失,所以在查询环节不做控制。会在更新环节,验证自己查询到的结果是否依旧有效。

  1. 乐观锁解决方案需要一个第三方标识的支持,可以是第三方数据版本id,或者是最后一次操作的时间戳等
  2. 乐观锁在执行查询时,会同时查询对应的版本id或时间戳
  3. 在更新时,会先验证之前查询到的版本id或时间戳是否依旧有效
  4. 如果有效,则继续执行更新操作,如果无效,则重新执行最初的查询操作。

悲观锁和乐观锁的利弊:

  1. 悲观锁实现方案简单,但是在查询阶段加排他锁会影响并发查询的效率
  2. 乐观锁不会影响并发查询的效率,但是在更新阶段需要重新验证,并且失败后需要不断重试
  3. 如果当前业务的查询多,更新少,优先使用乐观锁
  4. 如果当前业务的查询少,更新多,优先使用悲观锁

在这里插入图片描述

提问:

更新菜单信息的时候,在页面上选择了一个父菜单,在业务层更新方法中,是否需要先验证一下parentId是否存在?

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值