假死锁问题:
留着解决以后分享问题的解决思路.
转:http://tech.it168.com/a2009/0428/274/000000274236_4.shtml
1、错误提示:
2、原理知识:
2.1当我们在Forms中,试图更改block中数据的时候,Forms先发出一个对该行数据的select ... for update nowait查询,希望锁定该行(该锁是ORACLE行级X锁)。如果不能锁定,Forms提示Could not reserve records (2 trys). Keep trying?。如果用户选择No,Forms报告FRM-40510错误:ORACLE error: unable to reserve record for update or delete。
2.2 block加锁的模式。
block的锁定模式如果为automatic或immediate,会在修改记录时Forms会立即锁定数据库记录;如果设为delayed,在保存时Forms才尝试锁定记录。也就是说这个属性不管如何设置,都不会影响锁的模式,有影响的只是什么时候加锁而已。
2.4上面已经说过了,Forms在更数据行时,会先对该数据行加行级X锁。这个是Oracle写死在Forms中的,我们无法手工修改。你想不加锁也不行!Oracle够野蛮吧!^_^。不要拿Oracle推荐的transaction来压我,要明白这个世界上,不是全部的业务应用都需要严格的transaction。
2.5即使前面的查询锁定步骤成功,Forms还要比较查询结果和当前行的值是否一致。如果两者不完全相同,Forms抛出FRM-40654(记录已经被另一个用户更新,重新查询以查看修改)错误。这么做主要是为了防止lost update的情形,不让用户根据过时的数据来做出修改。这一点请认真理解哦?
3、解决方法:
3.1避免在TRIGGER中直接使用UPDATE语句,这样会造成Forms上的数据与Oracle数据库的数据不一致,从而造成FRM-40654的错误。
3.2要是问题都是由方法3.1造成的,那么它就不是问题了。
3.2.1下面细讲造成这次造成Form假死锁的根本原因。被锁的记录-订单编号为2000000747:
3.2.2注意认真查看这条记录,我们注意到3967.8这个字段。^_^,至于为什么会注意到这个字段。我折腾了一周多,并且在ITPUB上反复认真学习FORM底层数据操作的原理,再加N*N次方TEST,最后才锁定这个字段。3967.8是“供方承担”的金额字段。经查数据字典又得知数据库字段名为“supply_pay”
3.2.3我们直接从数据库SELECT这个记录出来看看。
select hm.oe_head_number,hm.supply_pay from hek_ods_th_fee_m hm where hm.oe_head_number=‘2000000747‘
看清楚了吗?supply_pay数据库的值为3967.799796,而FORM界面上的值却为3967.8。也就是说FORM自动帮我们四舍五入了。这样我们在FORMS上MODIFY这条记录时,FORM就会判断3967.8<>3967.799796,从而报FRM-40654的错误。而我们呢?却被误导一直在数据库锁方面找问题。
于是,我们总结出,可恶的ORACLE自作聪明,帮我们四舍五入了。可是我们真需要四舍五入吗?就算是要,自已加个ROUND不就得了吗?这不能不说是FORMS一个BUG!这也再次提醒我们不能对ORACLE太崇拜了哦?