m6米乐安卓版下载-米乐app官网下载
8

oracle死锁导致的数据库卡死情况处理 -m6米乐安卓版下载

狗剩儿 2022-02-28
1111

客户的一台oracle 19c rac数据库,其中的一个实例出先hang死的情况,严重影响业务访问使用!应用人员当时已无法操作数据库,尝试进行杀死死锁的session,但未起到效果。


接受问题处理第一步还是先观察后台alert日志,发现有ora-00060错误,并伴随着十几秒很快频率的redo切换,并生成了大量trc文件,数据库redo大小是2g。
根据开发人员的描述是他们修改了一个存储过程,运行存储过程导致,但现在数据库hang死业务人员无法编译存储过程。
所以思路为:优先杀死相应session,再查看trc文件定位死锁位置!
但杀死session后死锁还是存在,os层杀死对应pid后数据库可以操作!


oracle上的死锁一般出现于“行级锁”的环形依赖情况下:

有记录a、b,事务t1、t2,现在t1、t2并发执行update(或delete)a b
事务t1操作的顺序为a-b,正常情况下会先后锁住a和b
事务t2操作的顺序为b-a,正常情况下会先后锁住b和a
t1、t2并发执行,t1锁住a 同时 t2锁住b;
t1操作完a想要锁住b,但b已被t2锁住,t1等待中;t2操作完b想要锁住a,但a已被t1锁住,t2等待中;
由于t1、t2都在等待又都不释放,因此造成死锁。

当死锁越来越多的时候,数据库连接被耗尽,不再能接受新的连接;数据库服务器的cpu和内存也可能会不够用了……程序猿就悲剧了。

解决办法:

在事务开始时或开始前先对操作数据按统一规则排序。

例如:按a-b顺序排序,使得t1、t2操作的顺序都为a-b,假设t1、t2并发执行时t1锁住了a;则t2只能等待a的锁了,b就没有机会被t2锁住了;这样t1就可以顺利锁住b,并顺利执行;当t1执行完成,释放a、b,t2就可以继续执行了。

从线上死锁的情况来看,主要发生在以下两种场景:

① 在同一个事务中无序的update或delete多条记录,事务并发执行可能会有死锁。
② 没有事务,但执行单条update或delete sql时,如果update或delete所影响的记录数大于1,也有可能出现死锁。

对于第①种场景可以使用前述的解决办法处理,即先排序后执行;

对于第②种场景的解决办法如下:

先用select查询出需要操作的记录主键,按主键排序,再通过主键一条一条迭代执行。

不过将一条语句变成多条语句执行会破坏原有的事务(jdbc默认事务:一条sql语句即一个事务),无法保证操作的原子性了,这就需要将这些操作放入一个事务中。或者可以使用 in 语句将其改造成一条sql,例如:update … where id in ( 1,2,3,4… ) …,这样效率会比多条sql语句高一些,而且 in 是可以命中索引的。


死锁查询:

select s.username,l.object_id, l.session_id,s.serial#, s.lockwait,s.status,s.machine,s.program from v$session s,v$locked_object l where s.sid = l.session_id;

username:死锁语句所用的数据库用户;
sid: session identifier, session 标示符,session 是通信双方从开始通信到通信结束期间的一个上下文。
serial#: sid 会重用,但是同一个sid被重用时,serial#会增加,不会重复。
lockwait:可以通过这个字段查询出当前正在等待的锁的相关信息。
status:用来判断session状态。active:正执行sql语句。inactive:等待操作。killed:被标注为删除。
machine: 死锁语句所在的机器。
program: 产生死锁的语句主要来自哪个应用程序。

查看引起死锁的语句:

select sql_text from v$sql where hash_value in (select sql_hash_value from v$sql where hash_value in (select sql_hash_value from v$session where sid in (select session_id from v$locked_object));

kill掉死锁:

通过死锁查询得到对应sid、serial#,使用有权限的用户执行:

alter system kill session ‘sid, serial#’;

如果未能成功释放死锁该如何处理:

kill掉死锁后我们再查询下死锁:
select s.username,l.object_id, l.session_id,s.serial#, s.lockwait,s.status,s.machine,s.program from v$session s,v$locked_object l where s.sid = l.session_id;

那么有可能死锁的status状态变为了killed,但是此状态是无法释放资源的,那就需要通过sid去找到对应的pid进行系统层面的kill。

查vkatex parse error: expected 'eof', got '#' at position 29: …lect sid,serial#̲,paddr from v$session where sid=‘刚才查到的sid’
查v$process视图:

select spid from v$process where addr=‘刚才查到的paddr’;

kill -9 刚才查出的spid

最后修改时间:2022-03-01 17:48:38
「喜欢文章,快来给作者赞赏墨值吧」
2人已赞赏
【米乐app官网下载的版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论

网站地图