原标题:案例分析:你造吗?有个ORA-60死锁的解决方案
关注↑↑↑我们获得更多精彩内容!
问题综述
1
这段时间应用一直被一个诡异的 ORA-00060 的错误所困扰,众所周知,造成 ORA-00060 的原因是由于应用逻辑,而非 Oracle 数据库自己,之所以说诡异(“诡异”可能不准确,只能说这种场景,以前碰见的少,并未刻意关注),是因为这次不是常见的,由于读取数据顺序有交叉,导致ORA-00060,关于读取数据顺序错误,导致ORA-00060的错误场景,可以参考《ORA-00060的示例与若干场景》(https://blog.csdn.net/bisal/article/details/14227997)。
问题引入
2
再说我碰见的问题之前,引用一些 JL 大神《Oracle Core》,对于死锁的一些介绍,一些 (易混淆/不清晰) 概念,后面可能会用上。
Oracle 用户群里一个众所周知的说法是“读不阻塞写,写不阻塞读”,但这仅限于数据级别;当深入到底层的原始内存级别时,有时候读者必须阻塞写者才行,并且单个写操作必须阻塞其他所有操作。
每个由事务修改的数据(或索引)块都会在他的事务列表中引用该事务表槽。执行事务的会话都会为事务表槽创建一个排队资源(类型为 TX,id1 表示 undo 段号和槽号,id2 表示槽序列号)来锁定他,并将一个排队( enqueue )附加到这个资源上-具体来说,是 x$ktcxb 中的一行,而不是 x$ksqeq- 锁模式为 6(独占锁)。
混淆:
1. 当然可能有多个会话陷入循环等待,死锁不仅仅限于两个会话之间,尽管最常见的是两个。
2. 尽管模式6类型的TX锁是死锁中最常见的,但任何时候只要等待一个锁,都有可能会出现ORA-00060场景。
死锁场景:
1. 两个会话试图插入相同的主键值。
2. 一个会话在另一个会话删除父行时插入一行到子表中。
3. 一个会话插入一条父行,然后另一个会话在父行提交前插入子行。
4. 两个会话试图删除由同一个位图索引块(chunk)所覆盖的行。
本质上讲,如果由于索引(或由这些索引关联的约束)争用,导致你必须等待其他会话提交,那么你会看到一个模式 4 的 TX 等待。甚至有一个不是由编码问题引起的索引情况-当你等待其他会话完成索引块分裂时。
如下是官方文档,对于 TX 锁的介绍,字面含义“行锁”(“行锁”是否正确?后面 JL 帖子回复,会纠正这个错误),
Row Locks (TX)
A row lock, also called a TX lock, is a lock on a single row of table. A transaction acquires a row lock for each row modified by anINSERT,UPDATE,DELETE,MERGE, orSELECT... FORUPDATEstatement. The row lock exists until the transaction commits or rolls back.
Row locks primarily serve as a queuing mechanism to prevent two transactions from modifying the same row. The database always locks a modified row in exclusive mode so that other transactions cannot modify the row until the transaction holding the lock commits or rolls back. Row locking provides the finest grain locking possible and so provides the best possible concurrency and throughput.
If a transaction obtains a lock for a row, then the transaction also acquires a lock for the table containing the row. The table lock prevents conflicting DDL operations that would override data changes in a current transaction. Figure illustrates an update of the third row in a table. Oracle Database automatically places an exclusive lock on the updated row and a subexclusive lock on the table.
TM锁的介绍,
Table Locks (TM)
A table lock, also called a TM lock, is acquired by a transaction when a table is modified by anINSERT,UPDATE,DELETE,MERGE,SELECTwith theFORUPDATEclause, orLOCKTABLEstatement. DML operations require table locks to reserve DML access to the table on behalf of a transaction and to prevent DDL operations that would conflict with the transaction.
这是锁类型介绍,不同的锁模式,代表了不同的锁粒度,
问题背景及问题现象
3
先说下我的问题背景,
1. 这是高并发的一个 OLTP 应用。
2. 应用采用了多线程处理逻辑。
问题现象:
1. 数据库层面出现大量 “enq: TX - row lock contention”,行锁等待。
2. 应用进程会话,hang 在 DELETE 删除一张父表的操作上,20+ 分钟。
3. 在这 20 分钟的期间,非常多的应用进程会话,执行 INSERT 子表记录的时候,提示 ORA-00060 错误,经过统计,总计共有 160 个会话,提示 ORA-00060 错误,换句话说,所有 INSERT 提示 ORA-00060