MySQL中的update操作与锁机制

科技公元 数据库 2024-08-12

MySQL中的update操作与锁机制

引言

在日常的数据库操作中,我们经常会使用 UPDATE语句来修改数据。然而,在面对高并发场景时,我们是否曾思考过:多个 UPDATE操作是否会同时修改同一条记录?换句话说,MySQL的 UPDATE操作是否会自动加锁呢?

一、MySQL的锁机制简介

实际上,当我们在MySQL中进行 UPDATE操作时,系统确实会自动加锁,以确保数据的完整性和一致性。特别是在使用InnoDB存储引擎,并且采用可重复读的隔离级别时,这一特性更为明显。

二、InnoDB存储引擎的锁机制

在InnoDB存储引擎中,如果更新操作涉及到索引查询,那么会加行锁;如果需要查询整个表,则会加间隙锁(也称为临键锁)。这种锁机制有效地防止了多个事务同时修改同一条记录,从而避免了数据的不一致性。

三、案例分析

为了更好地理解这一机制,我们来看一个实际案例。假设我们有一个福利码兑换系统,每个福利码只能兑换一次,我们需要通过 UPDATE操作来更新库存。

线程A开启事务进行兑换id = 2 的福利码:sql

代码解读
复制代码
set autocommit=0; BEGIN; update koc_reward set remain_num = remain_num - 1 where id =2 and remain_num > 0; COMMIT;

此时,如果线程B也尝试查询并兑换同一个福利码:sql

代码解读
复制代码
update koc_reward set remain_num = remain_num - 1 where id =2 and remain_num > 0;

最终结果:

线程A事务还没提交的,线程B也对改福利码进行扣库存操作,就会被阻塞,直到线程A提交了,可以看到线程B在阻塞着。

MySQL中的update操作与锁机制

A线程提交事务,线程B才继续执行,此时库存已经没了,线程B就会更新 0 行,说明库存大于 0 的数据已经没有了。

MySQL中的update操作与锁机制

四、乐观锁与版本号控制

除了上述的锁机制外,我们还可以通过乐观锁和版本号控制来进一步提高系统的并发性能。在更新数据时,我们可以增加库存校验或其他版本号字段校验,从而实现乐观锁的效果。

MySQL中的update操作与锁机制

例如,在上面的案例中,我们在 WHERE子句中除了id主键外,还额外加了 remain_num > 0的条件。这样,其他线程在执行 UPDATE操作时,都会先查询满足 remain_num > 0条件的数据。如果去掉这一条件,虽然线程B在执行 UPDATE操作时也会加锁,但它仍然会查询id = 2的数据并直接扣减 remain_num,从而导致库存溢出。

五、总结

综上所述,MySQL的 UPDATE操作在处理并发请求时会自动加锁,以确保数据的完整性和一致性。同时,结合乐观锁和版本号控制等策略,我们可以进一步优化系统的并发性能。

转载来源:https://juejin.cn/post/7400325741441368101

Apipost 私有化火热进行中

评论