关于更新丢失的处理

关于更新丢失的处理

预备知识

关于隔离性

概述

在《关于隔离性》中,我们提到了更新丢失的问题。我们先来简单回顾下,如果多个用户按照如下流程并行地对数据库中的某个字段进行递增,就会出现更新丢失。

-- x为程序变量
begin;
x = select value from test;
x += 1;
update test set value = x;
commit;

我们提到了一些数据的Repeatable Read和Serializable隔离级别可以解决更新丢失的问题。我们还提到,这样实现递增的方式是非常扯淡的,通过一些其他的技术手段完全可以避免更新丢失,下面我们就来看看这些方法。

原子写操作

如果数据库支持原子写操作,那么最简单的方式就是使用如下SQL语句:

update test set value = value + 1;

所谓数据库支持原子操作,是指对于上述SQL,数据库总是获取最新的value值(本地读),然后对其值进行递增。

显示加锁

第二种方式是对需要修改的行显示加互斥锁,这样就将并行事务转为串行事务,具体流程如下:

-- x为程序变量
begin;
x = select value from test for update;
x += 1;
update test set value = x;
commit;

这种方式只是在原有流程的查询阶段加上了for update,这样事务就变为了串行。

Compare And Set

Compare And Set(CAS)是用于实现自旋锁的手段,这里也可以用来解决数据库的更新丢失,实现思路非常简单。

begin;
old_value = select value from test for update;
new_value = old_value + 1;
update test set value = new_value where value = old_value;
commit;

这种方式,一旦有其他事务对value进行了更新操作,那么就一定不满足value = old_value这个条件。CAS还有一种更通用的做法,给表添加一个版本列,然后采用如下流程:

begin;
(x,old_version) = select value, version from test for update;
x += 1;
update test set value = x, version = version + 1 where version = old_version;
commit;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值