jdbc事务引起的db session问题
从15年四月份开始,某项目组线上服务老反馈有服务挂掉问题,具体表现为服务不可用,但java进程是存活状态。经排查,发现是大量写操作线程在等待数据库返回。当时第一反映是数据表死锁了,导致线程等待,因此先入为主地做了判断,也如是交待项目组开发人员。现在看来,技术人员最忌讳的是自以为是。
自此以为问题结束了,但4月份后,陆续会听到类似的问题再出现,由于该项目我不直接处理,后续问题也未反馈到我手上,也不以为意,直到最近一个月,线上服务一再出问题,几经辗转还是回到我手上了。
问题恶心的地方在于不能稳定复现,折腾了一两天,查了业务代码,实在是太乱,加之现象十分诡异,通过oracle的视图定位,竟然是select语句造成了行锁,导致其他的update语句等待。查询语句如下:
select ls.osuser os_user_name,ls.username user_name,ls.type lock_type,
o.object_name object,decode(ls.lmode,1,null,2,'Row Share',3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive',null) lock_mode,o.owner,
ls.sid,ls.serial# serial_num,ls.id1,ls.id2,ls.lockwait from sys.dba_objects o,
(select s.osuser,s.username,l.type,s.lockwait,l.lmode,s.sid,s.serial#,l.id1,l.id2 from v$session s,v$lock l where s.sid=l.sid) ls
where o.object_id=ls.id1 and o.owner<>'SYS' order by o.owner,o.object_name
这个现象让我十分崩溃,已经超出了我的认知能力,无法想象为何一个select语句能导致行锁。沉下心来查oracle各种相关视图,终于发现一点端倪:block session的状态是inactive,这意味着block session已经执行完毕,只是未提交。这点通过java的线程也能得到佐证。为了进一步验证,在oracle sqlplus开两个客户端,模拟相关操作,终于复现了一样的场景。
接下来的事情变得简单些,排查java代码中哪些事务未提交。最终发现,开发人员在使用nutz事务时,采用了非官方的写法,而使用方式又有问题,导致事务未提交。