第一类丢失更新(回滚丢失,Lost update)

A事务撤销时,把已经提交的B事务的更新数据覆盖了。这种错误可能造成很严重的问题,通过下面的账户取款转账就可以看出来:

时间

取款事务A

转账事务B

T1

开始事务

 

T2

开始事务

T3

查询账户余额为1000元

T4

查询账户余额为1000元

T5

汇入100元把余额改为1100元

T6

提交事务

T7

取出100元把余额改为900元

T8

撤销事务

T9

余额恢复为1000 元(丢失更新)

A事务在撤销时,“不小心”将B事务已经转入账户的金额给抹去了。

SQL92没有定义这种现象,标准定义的所有隔离界别都不允许第一类丢失更新发生。

第二类丢失更新(覆盖丢失/两次更新问题,Second lost update)

A事务覆盖B事务已经提交的数据,造成B事务所做操作丢失:

时间

转账事务A

取款事务B

T1

 

开始事务

T2

开始事务

T3

查询账户余额为1000元

T4

查询账户余额为1000元

T5

取出100元把余额改为900元

T6

提交事务           

T7

汇入100元

T8

提交事务

T9

把余额改为1100 元(丢失更新)

上面的例子里由于支票转账事务覆盖了取款事务对存款余额所做的更新,导致银行最后损失了100元,相反如果转账事务先提交,那么用户账户将损失100元。

第二类丢失更新,实际上和不可重复读是同一种问题。

有些系统中第二类丢失更新可能就影响很大了,举个简单的例子:
财务系统加工资,若公司本次调薪决定给员工张三加1k人民币,财务部两名操作人员A和B,过程情况若是这样的:
1)A操作员在应用系统的页面上查询出张三的薪水信息,然后选择薪水记录进行修改,打开修改页面但A突然有事离开了,页面放在那没有做任何的提交。
2)这时候B操作员同样在应用中查询出张三的薪水信息,然后选择薪水记录进行修改,录入增加薪水额1000,然后提交了。
3)这时候A操作员回来了,在自己之前打开的薪水修改页面上也录入了增加薪水额1000,然后提交了。
其实上面例子操作员A和B只要一前一后做提交,悲剧就出来了。后台修改薪水的sql:update 工资表 set salary = salary + 增加薪水额 where staff_id = ‘员工ID’。这个过程走下来后结果是:张三开心了这次涨了2k,操作员A和B都郁闷了。

解决思路:
       基本两种思路,一种是悲观锁,另外一种是乐观锁;
简单的说就是一种假定这样的问题是高概率的,最好一开始就锁住,免得更新老是失败;另外一种假定这样的问题是小概率的,最后一步做更新的时候再锁住,免得锁住时间太长影响其他人做有关操作。

解决方案1(悲观锁)
 a.传统的悲观锁法(不推荐):
         以上面的例子来说明,在弹出修改工资的页面初始化时(这种情况下一般会去从数据库查询出来),在这个初始化查询中使用select ...for update nowait, 通过添加for update nowait语句,将这条记录锁住,避免其他用户更新,从而保证后续的更新是在正确的状态下更新的。然后在保持这个链接的状态下,在做更新提交。当然这个有个前提就是要保持链接,就是要对链接要占用较长时间,这个在现在web系统高并发高频率下显然是不现实的。
   
b.现在的悲观锁法(推荐优先使用):
        在修改工资这个页面做提交时先查询下,当然这个查询必须也要加锁(select ...for update nowait),有人会说,在这里做个查询确认记录是否有改变不就行了吗,是的,是要做个确认,只是你不加for update就不能保证你在查询到更新提交这段时间里这条记录没有被其他会话更新过,所以这种方式也需要在查询时锁定记录,保证在这条记录没有变化的基础上再做更新,若有变化则提示告知用户。

解决方案2(乐观锁)
a.旧值条件(前镜像)法:
       就是在sql更新时使用旧的状态值做条件,SQL大致如下 Update table set col1 = newcol1value, col2 = newcol2value…. where col1 = oldcol1value and col2 = oldcol2value….,在上面的例子中我们就可以把当前工资作为条件进行更新,如果这条记录已经被其他会话更新过,则本次更新了0行,这里我们应用系统一般会做个提示告知用户重新查询更新。这个取哪些旧值作为条件更新视具体系统实际情况而定。(这种方式有可能发生阻塞,如果应用其他地方使用悲观锁法长时间锁定了这条记录,则本次会话就需要等待,所以使用这种方式时最好统一使用乐观锁法。)

b.使用版本列法(推荐优先使用):
       其实这种方式是一个特殊化的前镜像法,就是不需要使用多个旧值做条件,只需要在表上加一个版本列,这一列可以是NUMBER或 DATE/TIMESTAMP列,加这列的作用就是用来记录这条数据的版本(在表设计时一般我们都会给每个表增加一些NUMBER型和DATE型的冗余字段,以便扩展使用,这些冗余字段完全可以作为版本列用),在应用程序中我们每次操作对版本列做维护即可。在更新时我们把上次版本作为条件进行更新。

c.使用校验和法(不推荐)

d.使用ORA_ROWSCN法(不推荐)

结论:
        综上所述,我们对丢失更新问题建议采取上面的悲观锁b方法或乐观锁b方法(红字体已标注),其实这两种方式的本质都一样,都是在更新提交时做一次查询确认在更新提交,我个人觉得都是乐观的做法,区别在于悲观锁b方法是通过select..for
update方式,这个可能会导致其他会话的阻塞,而乐观锁b方法需要多一个版本列的维护。

个人建议:在用户并发数比较少且冲突比较严重的应用系统中选择悲观锁b方法,其他情况首先乐观锁版本列法。

数据库第一类第二类丢失更新相关推荐

  1. 第一类第二类丢失更新

    第一类丢失更新 A事务撤销时,把已经提交的B事务的更新数据覆盖了.这种错误可能造成很严重的问题,通过下面的账户取款转账就可以看出来: 时间 取款事务A 转账事务B T1 开始事务   T2 开始事务 ...

  2. [学习笔记]第一类/第二类斯特林数

    前置知识 · 组合数学基础 · 容斥原理 · 生成函数 · FFT/NTT · 多项式exp,多项式ln,多项式快速幂,多项式平移 一些规定 · 下降幂 xn‾=∏i=1n(x−i+1)x^{\und ...

  3. 第一类第二类斯特林数总结

    第一类Stirling数是有正负的,其绝对值是包含n个元素的集合分作k个环排列的方法数目. 递推公式为, S(n,0) = 0, S(1,1) = 1. S(n+1,k) = S(n,k-1) + n ...

  4. 高等数学_第一类第二类曲线积分(基本)

    公式内的带t的参数方程是把: 以x,y为变量的方程, 化为: x=什么什么t: y=什么什么t: 的参数方程的形式.再进行带入 (重点是注意t的取值范围) 例如: x²+y²=4化为:{手动画一个 x ...

  5. mysql 乐观锁 脏读_mysql 丢失更新1和2、脏读、不可重复读和幻读 事务隔离级别 悲观锁 乐观锁...

    事务是现代关系型数据库的核心之一.在多个事务并发操作数据库(多线程.网络并发等)的时候,如果没有有效的避免机制,就会出现以下几种问题: ( 第一类丢失更新 A事务撤销时,把已经提交的B事务的更新数据覆 ...

  6. OSPF中第一类外部路由和第二类外部路由的区别

    区别: 1.开销值 第一类外部路由的AS外部开销被认为和AS内部开销值是同一数量级的,因此第一类外部路由的开销值为AS内部开销值(路由器到ASBR的开销)与AS外部开销值之和: 第二类外部路由的AS外 ...

  7. 【组合数学】第一类,第二类斯特林数(Stirling),Bell数

    第一类斯特林数 定理: 第一类斯特林数S1(p,k)计数的是把p个对象排成k个非空循环排列的方法数. 证明:把上述定理叙述中的循环排列叫做圆圈 递推公式: S1(p,p)=1(p>=0),有p个 ...

  8. hdu 1556:Color the ball(第二类树状数组 —— 区间更新,点求和)

    Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  9. 曲面积分的投影法_在家学|第一类曲面积分与第二类曲面积分的计算

    利用投影法计算第一类曲面积分 设函数为定义在曲面上的连续函数.曲面的方程为.具有对和的连续偏导数,即此曲面是光滑的,且其在平面上的投影为可求面积的.则 如果曲面由方程给出,在坐标面上的投影区域为,函数 ...

最新文章

  1. java selenium (十四) 处理Iframe 中的元素
  2. Python 使用控制台运行带有相对路径的指令时,是以运行文件为基准,还是以控制台当前路径为基准
  3. mysql数据库提示2005_Mysql数据库从本地导出 服务器上导入时报 ERROR 2005 HY000 Unknown MySQL ser...
  4. float排版c语言,如何解决因float带来的排版问题?
  5. CentOS 7 防火墙开启了哪些服务和端口?
  6. LinkedHashMap 与 HashMap区别
  7. LFFD:轻量级人脸检测器,不止是快
  8. ceph 代码分析 读_五大常见存储系统PK | Ceph、GlusterFS、MooseFS、HDFS、DRBD
  9. linux串口API编程
  10. yaahp层次分析法步骤_什么是层次分析法?(文末附yaahp软件)
  11. 340-写一个银行转账死锁问题并且解决
  12. 特斯拉Model 3进化不止 传统车企到底应该学什么?
  13. unity 设置image透明度_Unity透明效果-透明度测试
  14. Questasim覆盖率数据分析
  15. iOS 第三方登录之 微信登录
  16. 计算机应届毕业生怎么获得BATJ实习转正机会呢?
  17. python爬虫爬取豆瓣电影信息城市_Python爬虫入门 | 2 爬取豆瓣电影信息
  18. get请求获取不到参数
  19. 输出二叉查找树poj 2418 二叉查找树
  20. thinkpad E430 电源连接未充电的问题解决方法

热门文章

  1. c语言 结构与联合
  2. 133 十面埋伏的并发(二):自旋锁
  3. 为什么国外程序员钟爱Mac?竟然是这个原因~
  4. Python:XML文件解析
  5. 私募股权公司TorQuest Partners收购Bartek Ingredients Inc.
  6. 行业观点|鞋企转战个性化定制 打响新消费时尚
  7. Apache服务网页和安全优化(带有小实验,轻松学习)
  8. IDEA代码抽取为方法快捷键
  9. PDF文件转为缩略图
  10. 柯本气候分类法的 C++实现