Oracle DML 操作的死锁与阻塞

posted by 野猫 on

版权声明:本文为 @WildMeowth 的原创文章,可以转载,但请务必注明作者和出处!!!原文链接:wildmeowth

项目中经常出现数据库阻塞和死锁的情况且数据库DML操作会比较常见,由此引发思考

DML 操作

数据库DML 语句常用关键字: insert、update、delete、select等

阻塞与死锁

其中insert、update、delete 以及 select for update都会在失误提交或回滚前上锁(表的共享锁,行上的排它锁)

当事务1一直没提交或回滚,另一个事务2操作同一行时就会等待锁释放而造成阻塞

而若事务1操作表1行1且未提交或回滚,事务2操作表2行2未提交,此时事务1操作表2行2,事务2操作表1行1,这种互相阻塞的情况就是死锁

阻塞比死锁还可怕

解决思路

  • 按同一顺序访问对象

如果所有并发事务按同一顺序访问对象,及按顺序申请锁,这样不会相互等待,则发生死锁的可能性降低

  • 避免事务中的用户交互

避免编写包含用户交互的事务,因为没有用户干预的批处理运行速度远快于等待用户响应时的查询速度

  • 保持事务简短(大事务拆小)并处于一个批处理中

运行时间越长,等待时间就越长,造成死锁的机会就越高。在同一个事务中尽可能做到一次锁定所有需要的资源,减少死锁概率

  • 使用更低级别的隔离级别

在业务允许下,尽可能使用较低的隔离级别

  • 合理的索引

索引不当或索引过少导致全表扫描行级上升表级锁,多个这样的事务执行后,就很容易产生死锁和阻塞