数据库并发导致的脏读 不可重复读 幻读的处理方法

在做ERP订单接入仓库库存的时候出现了一个问题。下单会读取该商品是否有库存。如果有那么就下单 减去(可下单库存,物理库存不变) 没有则提示库存不足

在并发情况下就会导致 u1用户下单编号为1的商品1个  u2用户也下单编号为1的商品1个。编号为1的商品库存只有1个。 那么当u1在读取出数据的时候发现库存有一个 但是还没有写入库存的操作   u2也下单成功并提交  那么就会导致数据错乱 本来应该是只有u1会下单成功u2则提示库存不足

这里可以用事物的隔离机制或乐观锁来解决

事物是一个逻辑单元

原子性:事物里面是一块逻辑单元 要么都执行 要么都不执行

一致性:事物处理前与处理后的状态的要是一致的(a账户有200元 b账户有300元   共计500元  a账户给b账户转账100元。事物处理后2个账户总额也为500元)

隔离性:每个事物都有自己的数据空间,使事物的处理结果不会被别的事物所影响

持久性:事物提交 数据就永久的保存下来了

事物的隔离级别

Read uncommitted  读取未提交的

这个隔离级别可能会导致脏读。它可以读取别的事物更改后并未提交的数据。比如以仓库库存判断为例子  在一个事物里面读取商品 并修改商品库存为0但是事物还没有提交     另外一个事物下单 发现没有库存 提示库存不足  这个时候第一个事物取消 导致脏读

Read committed   读取已经提交的

这个隔离级别能够避免脏读。因为只能读取事物已经提交的数据。但是会出现不可重复读  还是以仓库为例子 一个事物下单一个商品 数量为1  库存也为1  当下单的事物还没有提交 另外一个事物已经下单并修改了库存为0 造成数据混乱  因为这个事物隔离级别虽然只能读取已经提交的 但是能够修改未提交的数据

Repeatable read  可重复读

这个事物隔离级别可以解决上面的那种情况  当一个事物在处理某条数据的时候 别的事物既不能读取也不能修改  但是会造成幻读 因为不能修改和读取未提交的数据 但是可以插入和删除数据  比如个人账户消费为例子 一个事物查询用a当月消费记录总和来做信用评分 select sum(money) from table  读取出来当月消费2000元 。当事物还没有提交  用户a老婆这个时候在美容院消费5000  那么table表新增一条消费记录为5000的数据  这个时候出现幻影读(事物读取数据与实际数据不符)

Serializable 序列化

这个隔离级别最高 能够避免 脏读 不可重复读 幻影读  但是效率低(既一个事物在操作某条数据的时候 别的事物不能读取和修改这条数据  也不能往表里插入数据)

根据不同的并发场景选择不同的事物隔离机制

乐观锁

即使用数据在解决并发情况下数据不一致的情况

以仓库库存为例

在仓库表增加一个最后修改时间字段 并将它作为条件

仓库库存表拥有a产品 可下单库存1个

u1用户下单a产品 读取出来判断库存是否充足 充足的话 在事物里面下单并更新可用库存 update stok set num-=1,lastupdatedatetime=datetime.now where id=a and lastupdatedatetime=上一次的修改时间

就算在u1提交之前别的事物比他先提交 那么u1 提交的时候 lastupdate被别的事物更新了 则条件不成立提交失败(受影响行数为0 回滚下单操作)

注:Oracle 只支持Serializable Read committed

时间: 2024-10-27 13:21:10

数据库并发导致的脏读 不可重复读 幻读的处理方法的相关文章

mysql事务隔离级别/脏读/不可重复读/幻读详解

一.四种事务隔离级别 1.1 read uncommitted 读未提交 即:事务A可以读取到事务B已修改但未提交的数据. 除非是文章阅读量,每次+1这种无关痛痒的场景,一般业务系统没有人会使用该事务隔离级别,标准实在太宽松了. 1.2 read committed 读已提交(简称RC) 即:事务A只能读取到事务B修改并已提交的数据. 这个级别相对要严格一些,至少是要等其它事务把变更提交到db,才能读取到,听上去蛮靠谱的.但是有些业务场景,比如会员系统中,如果要在一个事务中,多次读取用户身份,判

[MySQL]对于事务并发处理带来的问题,脏读、不可重复读、幻读的理解与数据库事务隔离级别 - 分析脏读 & 不可重复读 & 幻读

刚开始写博客.. 写的太low. 1.数据库的两种读,每种读读的数据版本不一样,所以也称为MVCC,即多版本并发控制 a) 快照读 select * from where xxx  这种形式的都是快照读. b) 当前读 update , insert ,delete ,select xx from xx for update ,  in share mode 都是当前读 当前读会等待,不会返回数据的历史版本 2.mvcc 的实现原理 mvcc是基于read view.活跃事务列表 做的,以后的文

理解数据库事务隔离级别以及脏读, 不可重复读, 幻读(转)

  转自:http://blog.csdn.net/sunxing007/article/details/6427290 数据库事务的4个特性: 原子性(atomic): 都成功或者都失败: 一致性(consistency):事务操作之后,数据库所处的状态和业务规则是一致的;比如a,b账户相互转账之后,总金额不变: 隔离性(isolation):操作中的事务不相互影响; 持久性(durability):事务提交后被持久化到数据库. 脏读,不可重复读, 幻读 幻读phantom read:事务1读

数据库事务隔离级别 - 分析脏读 & 不可重复读 & 幻读

一 数据库事务的隔离级别 数据库事务的隔离级别有4个,由低到高依次为Read uncommitted .Read committed .Repeatable read .Serializable ,这四个级别可以逐个解决脏读 .不可重复读 .幻读这几类问题. 1. Read UnCommitted(读未提交) 最低的隔离级别.一个事务可以读取另一个事务并未提交的更新结果. 2. Read Committed(读提交) 大部分数据库采用的默认隔离级别.一个事务的更新操作结果只有在该事务提交之后,另

商品分类-商品详情-数据库脏读-不可重复读-幻读-订单生成

商品详情的无限极分类 --北京 --朝阳区 ---上海 --松江 --大学城 def get_level(data): data_list=[] for item in data: if item['parent_id']==0: item['level']=0 else: item['level']=1 data_list.append(item) return data_list data=[ {"cat_id":1,"name":"北京",

脏读 不可重复读 幻读

脏读(Dirty Read)     脏读意味着一个事务读取了另一个事务未提交的数据,而这个数据是有可能回滚 不可重复读(Unrepeatable Read) 不可重复读意味着,在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据.这是由于查询时系统中其他事务修改的提交而引起的. 例如:事务B中对某个查询执行两次,当第一次执行完时,事务A对其数据进行了修改.事务B中再次查询时,数据发生了改变 幻读(phantom read) 幻读,是指当事务不是独立执行时发生的一种现象,例如第一个事务对

脏读 不可重复读 幻读以及第一、二类丢失更新

http://blog.csdn.net/gaoshan_820822/article/details/4582561 脏读(Dirty Read) 脏读意味着一个事务读取了另一个事务未提交的数据,而这个数据是有可能回滚. 不可重复读(Unrepeatable Read) 不可重复读意味着,在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据.这是由于查询时系统中其他事务修改的提交而引起的. 例如:事务B中对某个查询执行两次,当第一次执行完时,事务A对其数据进行了修改.事务B中再次查询时

了解数据库中脏读+不可重复读+幻影读

"读现象"是多个事务并发执行时,在读取数据方面可能碰到的状况.先了解它们有助于理解各隔离级别的含义.其中包括脏读.不可重复读和幻读. 脏读: 脏读又称无效数据的读出,是指在数据库访问中,事务T1将某一值修改,然后事务T2读取该值,此后T1因为某种原因撤销对该值的修改,这就导致了T2所读取到的数据是无效的. 脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交(commit)到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据.因为这个数据是还没有提交

数据库事务隔离级别、脏读、重复读、不可重复读、幻读

数据库事务四种隔离级别 1.Read Uncommitted(读未提交) :事务中的修改,即使没有提交,其他事务也可以看得到,会导致“脏读”.“幻读”和“不可重复读取”. 2.READ COMMITTED (读提交):大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”,但不能避免“幻读”和“不可重复读取”.该级别适用于大多数系统. 3.REPEATABLE READ(可重复读) :保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的