场景(问题)描述以下:数据库
0,用户A、B同时打开一个页面,页面显示,客户表T_CUSTOMER字段(C_NAME、C_AGE)并发
姓名:张三,年龄:25oracle
1,A 将姓名“张三”改成“张三1”,而后保存事务
2,B 将年龄“25”改成“30”,而后保存开发
这样A的操做就被覆盖了,姓名又变回“张三”了,你们通常怎么到处这种状况?get
这里给出一个较易用的解决方案原型
给表添加一字段:LAST_UPDATE,即最后更新时间同步
回放场景效率
0,用户A、B同时打开一页面,面页显示:原理
姓名:张三,年龄:25,LAST_UPDATE:2008-10-17 13:45:00
1,A 将姓名“张三”改成“张三1”,而后保存
重点在这里:更新数据时WHERE条件里多一条件:AND LAST_UPDATE = '2008-10-17 13:45:00'
更新成功,此时触发器会将当前时间“2008-10-17 13:46:00”赋值给LAST_UPDATE
2,B 将将年龄“25”改成“30”,而后保存
B更新数据时WHERE条件里也有这个条件:AND LAST_UPDATE = '2008-10-17 13:45:00',但此时LAST_UPDATE的值已经在A修改记录时变成2008-10-17 13:46:00
下面要作的就是给出提示了:喔哟,此信息在你发呆这段时间已被人改过啦,因此你须要返工。
【问题】在之前的系统开发中,常常遇到一个一样问题,就是多个用户同时并发操做一条记录,此次在交易系统开发过程当中,又出现了这样问题。好比交易商A提交单子,由审核人员B审核,此时A正在修改单位,B也正在查看这条记录,A先修改保存后B再审核保存,致使B审核经过的记录不是他所看到的。
【分析】仔细考虑问题,大概分析了三个方法, 并肯定了一个可行的方案,可能还有不完善的地方,但解决现有问题仍是绰绰有余的。
最早想的是在交易业务代码中用lock对修改方法加锁,运行时注入单例,而且对方法加同步锁,保证了业务数据的正确性, 可是效率低下,用户在使用中不方便,背离了系统能够并发操做的原则。
而后考虑使用悲观锁,此次运行时注入原型,并发操做效率提升, 可是,在同步处理数据库表时又形成锁表,这样并发效率依旧很低。
最后考虑乐观锁, 只是一种数据版本校验机制,它不作数据库层次上的锁定,须要在要并发操做的主表中加入一个"VERSION"字段或者“LASTUPDATETIME”,若是研究过oracle的SCN应该有殊途同归之妙,它的原理是这样:运行时注入原型,这时数据表并不锁住,只是每次update或insert时将VERSION更新, 当下次update,insert时,会校验VERSION,若是不一致,此时提示信息已经修改过了,而且在事务控制下rollback,这样,保证了数据的正确性,而且也不影响并发操做的效率。可是出现的问题是:若是A读了数据,将来及更新,B先更新了数据, 那么他将提交不上数据,由于VERSION已经失效,这样就形成了A从新读取数据,从新填写单据信息。 这也是乐观锁一个缺点,能够在更新前临时保存A填写的数据,再在跳转页中加载这些数据,保证了交易商不用麻烦再次输入这些数据,更新成功则清空这些临时数据