MySQL中的SELECT...forupdate(乐观锁和乐观锁)

原创
小哥 3年前 (2022-10-29) 阅读数 14 #mysql
文章标签 sql

一、MySQL悲观锁:

SELECT ...for update 是在MySQL悲观锁的应用。

1、何为MySQL悲观之锁?(对于悲观锁,有乐观锁,如下所述)

悲观锁定是对被修改的数据持悲观态度(认为数据被修改肯定会有并发问题),因此数据在整个数据处理过程中被锁定。悲观锁的实现往往依赖于数据库提供的锁定机制(只有数据库层提供的锁定机制才能真正保证数据访问的排他性,否则,即使在应用层实现锁定机制,也不能保证外部系统不会修改数据)。

在产品表t_product那里有一些田野p_status,p_status为1意味着该产品尚未放置,p_status为2意味着产品已经下单,所以当我们订购产品时,我们必须确保产品p_status为1。假设产品是p_id为1。如果没有使用锁,则操作如下:

--1.查询产品信息
select p_status from t_product where p_id = 1;
--2.根据产品信息生成订单
insert into t_order (id, p_id) values (001, 1);
--3.修改产品p_status为2
update t_product set status=2 where p_id = 1;

在高并发访问的情况下,这样的场景可能会有问题。如前所述,只有当p_status为1只有当产品可以下单时,上面的第一步,查询出商品。status为1。但当我们执行第三步时Update在操作过程中,其他人有可能先在产品上下单。p_status状态为已修改2然而,我们不知道数据是否被修改,这可能会导致相同的产品被下订单。2时间,使数据不一致。所以这条路不安全。

2,使用悲观锁来实现

在上面的场景中,产品信息从查询出来到修改,中间有一个处理订单的过程,使用悲观锁的原理就是,当我们在查询产品信息后就把当前的数据锁定,直到我们修改完毕后再解锁。那么在这个过程中,因为产品被锁定了,就不会出现有第三者来对其进行修改了。要使用悲观锁,我们必须关闭mysql数据库的自动提交属性。

--设置MySQL为非autocommit模式:
set autocommit=0;
--设置完autocommit在那之后,我们就可以进行正常的业务了。详情如下:
--0.开始事务
begin;/begin work;/start transaction; (三种中的一种可以,推荐start transaction是SQL-99标准启动一项交易。)
--1.查询产品信息
select p_status from t_product where p_id=1 for update;
--2.根据产品信息生成订单
insert into t_order (id,p_id) values (001,1);
--3.修改产品status为2
update t_product set p_status=2;
--4.提交事务
commit;/commit work;

假设有一个产品表t_product,里面有p_id跟p_name两个字段,p_id是主键。
例1: (明确指定主键,有了这个数据,row lock)
SELECT FROM t_product WHERE p_id=3 FOR UPDATE;
例2: (明确指定主键。如果没有这样的数据,则没有lock)
SELECT
FROM t_product WHERE p_id=-1 FOR UPDATE;
例2: (无主键,table lock)
SELECT FROM t_product WHERE p_name=电脑 FOR UPDATE;
例3: (主键不明确,table lock)
SELECT
FROM t_product WHERE p_id<>3 FOR UPDATE;
例4: (主键不明确,table lock)
SELECT * FROM t_product WHERE p_id LIKE 3 FOR UPDATE;
注1: FOR UPDATE 仅适用于InnoDB并且必须在事务块中。(start transaction/COMMIT)才能生效。
注2: 要测试锁的状况,可以使用MySQL 的Command Mode ,打开两个窗口进行测试。

以上是关于数据库主键对的内容。MySQL除了主键之外,索引的使用还会影响数据库的锁级别,因为悲观锁在大多数情况下依赖数据库的锁机制来确保操作的最大排他性。如果锁定时间过长,其他用户将无法长时间访问,从而影响程序的并发可访问性。同时,它对数据库的性能开销也有很大的影响,特别是对于长事务,这往往是无法承受的。因此,悲观锁的对立面是乐观锁。有关详细信息,请参阅以下介绍:

二、MySQL乐观锁:

乐观锁( Optimistic Locking ) 与悲观锁相比,乐观锁假设数据一般不会造成冲突,因此在提交和更新数据时,会正式检测到数据的冲突。如果发现冲突,将返回错误的用户信息,并由用户决定如何操作。那么,我们如何实现乐观锁呢,通常是通过以下几点2种方式:

1.使用数据版本(Version实现了记录机制,这是乐观锁最常用的实现之一。

数据版本是什么?也就是说,通常通过向数据库表添加数字类型来向数据添加版本标识符。 “version” 要实现的字段。在读取数据时,version这些字段的值被一起读取,并且每次都会更新数据。version价值加一。提交更新时,判断数据库表中对应记录的当前版本信息与第一次取出的版本信息相同。version如果数据库表的当前版本号与第一次取出时相同,则比较该值。version如果这些值相等,则会更新它们,否则它们将被视为过期数据。使用下图进行说明:

版权声明

所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除