oracle 表记录锁,记录一次oracle锁表排除经历

背景:功能代码都写好了,进入测试阶段后,测试妹子测功能的时候,一切数据填入都是对的也没有发生异常的情况下,突然开发的接口提示504了。

排查经过:用idea排查之后发现在某一段代码里面,该更新的数据sql貌似没有被执行,于是开始查看sql如下:update

A ad

set ad.status='1',

ad.update_date=sysdate,

ad.amount=#{Amount}

where ad.code = #{Code}

and ad.verify = #{verifyCode}

咋一看 这条sql是没有任何毛病的,放在PL-SQL里面也是可以执行的,那么就不是这个sql语句的问题,为了重现这个bug,于是叫测试重新测试一下。重新debug,开始怀疑没有执行这sql语句的原因是因为事物的缘故,后来才发现是因为 这条 sql 执行了但是一直在执行没有返回的结果,所以最后接口给出的504。

最后,猜测可能被锁表了,执行如下sql:SELECT object_name, machine, s.sid, s.serial#

FROM gv$locked_object l, dba_objects o, gv$session s

WHERE l.object_id = o.object_id

AND l.session_id = s.sid;

tips:执行这条sql 需要oracle DBA的权限,否则无法执行

查询出如图:

5f44669d9023f819b9cfa4031178418d.png

这就说明真的被锁了,执行如下sql,先把锁住的表释放掉:ALTER system kill session '630, 15423';

这里的后面两个数据就是 查询出来对应的SID 和 SERIAL#

到这一步,你觉得问题就解决了吗?

事实问题并没有解决掉,从代码层面看了一圈,我确定没有问题,那么我就去找测试,我说怎么操作出来的,看了半天,好像操作没什么问题,后来才知道,测试在测过程的时候,需要查询数据库某一个字段,然后填入,然后做功能测试,也就是这一个查询导致了死锁。他的sql语句如下:select * from A for update;

那么问题就来了,for update是什么鬼?相信很多牛牛们都可能不是很熟悉这个,大家用mysql 可能查询就是直接写select * from 某某表

关于for update 是什么玩意看如下内容:

如果只是select的话,Oracle是不会加任何锁的,也就是Oracle对select读到的数据不会有任何限制,虽然这时候有可能另外一个进程正在修改表中的数据,并且修改的结果可能影响到你目前select语句的结果,但是因为没有锁,所以select结果为当前时刻表中记录的状态。

如果加入了for update,则Oracle一旦发现(符合查询条件的)这批数据正在被修改,则不会发出该select语句查询,直到数据被修改结束(被commit),马上自动执行这个select语句。

如图:

5f44669d9023f819b9cfa4031178418d.png

说到这,原因出来了。如果在查询的时候加了for update并且没有commit的时候,再其他程序跑这个update 语句的时候表会被锁住,导致你程序的时候sql 没有执行响应,所以在查询的时候,建议不要轻易使用 for update

后面还有 oracle for update 和 for update nowait的知识扩展,就不继续多费笔墨了。

附上链接 有需要的可以自行学习查看:https://www.cnblogs.com/quanweiru/archive/2012/11/09/2762223.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值