在高并发的场景下,经常会遇到这种情形:
A请求过来,查询出来一条数据,举行update操作,与此同时B请求也在这个时刻过来,对这条数据举行查询,并举行操作。此时就会泛起B在A之后举行查询操作,然则现实B的数据却被A笼罩。

表名A,字段名为 number,如下的SQL语句:

甲操作 语句1:select num from store where id='1';

假设此时甲获取到 num= 99

乙操作 语句2:select num from store where id='1';

由于甲方还没有update操作,乙获也取到 num= 99
这时刻A举行update操作

update store set num =${num} +1 where id='1';

这时刻写入数据库的num即为100
此时B请求也发起了更新操作:

update store set num =${num} +1 where id='1';

这时刻我们的预期本应该是101的,然则现实上B又在数据库写入了100

解决方案:

(1)引入一个版本号的观点,在表A中增添一个version字段

甲操作 语句1:select num,version from store where id='1';

假设此时甲获取到 num= 99 version =1

乙操作 语句2:select num,version from store where id='1';

,

以太坊高度数据

www.326681.com采用以太坊区块链高度哈希值作为统计数据,联博以太坊统计数据开源、公平、无任何作弊可能性。联博统计免费提供API接口,支持多语言接入。

,

由于甲方还没有update操作,乙获也取到 num= 99 version=1
这时刻A举行update操作

update store set num =${num} +1 where id='1' and version = ${version};

这时刻写入数据库的num即为100, version =2
此时B请求也发起了更新操作:

update store set num =${num} +1 where id='1' and version = ${version} ;

这时刻发现条件version = 1不成立,由于上一步操作version已经为2了,以是update无法更新。

(2)解决方式:update A set number=number+1 where id=1; 语句直接处置

表名A,字段名为 number,如下的SQL语句:

语句1:update A set number=number+1 where id=1;
语句2:update A set number=number+2 where id=1;

假设这两条SQL语句同时被mysql执行,id=1的纪录中number字段的原始值为99,那么是否有可能泛起这种情形:
语句1和2由于同时执行,他们获得的number的值都是99,都是在10的基础上分别加1和2,导致最终number被更新为100或101,而不是102

这个实在就是 关系型数据库自己就需要解决的问题。首先,他们同时被MySQL执行,你的意思实在就是他们是并发执行的,而并发执行的事务在关系型数据库中是有专门的理论支持的- ACID,事务并行等理论,所有关系型数据库实现,包罗Oracle, MySQL都需要遵照这个原理。
简朴一点明白就是锁的原理。这个时刻第一个update会持有id=1这行纪录的 排它锁,第二个update需要持有这个纪录的排它锁的才能对他举行修改,正常的话, 第二个update会壅闭,直到第一个update提交乐成,他才会获得这个锁,从而对数据举行修改。
也就是说,根据关系型数据库的理论,这两个update都乐成的话,id=1的number一定会被修改成22。若是不是22, 那就是数据库实现的一个严重的bug。