深入剖析:insert 的enq: TM – contention

    xiaoxiao2023-03-24  5

    Lunar 拥有超过十年的 ORACLE SUPPORT 从业经验,曾经服务于ORACLE ACS部门,现就职于 ORACLE Sales Consultant 部门,负责的产品主要是 Exadata,Golden Gate,Database 等。

    编辑手记:此文通过分场景环环紧扣的测试,深入剖析了enq: TM – contention等待事件的原理,今日拣选与大家共享。

    结论:当外键无索引时

    1,对子表的insert操作所在的事务没有完成前,对于父表的DML操作(INSERT/UPDATE/DELETE)都会因为不能获得对子表的TM锁而出现enq: TM – contention。 2,在1的基础上,如果又有了对子表的insert,那么这个对子表的insert同样被阻塞,等待事件也是 enq: TM – contention。 3,对父表的insert会阻塞对父表的delete。同样的道理,此时对父表的insert也阻塞对父表的update pk操作。

    当没有索引的时候

    测试1, 在子表发生 Insert,然后在父表上有update操作

    Session 1: 对子表进行insert,不commit时:

    这是,我们看到,该回话在主表(1062788 DEPT)和子表(1062790 EMP)上都分别持有了 exclusive lock(LMODE=3)锁

    同时,该回话还持有一个tx锁(在子表 emp上)

    另开一个会话,观察锁:

    Session 2 : 然后,我们在父表做DML操作update:

    Session 3: 检查锁的变化

    这是我们看到,Session 2 在子表(1062790 EMP)上请求LMODE=4,并在主表(1062788 DEPT)上持有等待:enq: TM – contention

    这是很清晰,有blocker了,也就是Session 1(SID 321),此时该回话正在对子表(1062790 EMP)进行插入操作.

    换句话说,当外键无索引时,对子表的insert操作,会造成对父表的更新操作的阻塞。

    Session 4 更新父表:

    这是我们看到,session 4(sid 116)遵循了跟session 220同样的所规律

    这是我们在Session 1中执行commit,在Session 3中观察:

    可以看到Session 2和Session 4都完成了update: Session 2:

    这里我们看到,当外键无索引时,对子表的insert操作,会造成对父表的更新操作的阻塞,该阻塞直到子表的insert事务结束,才自动释放。

    测试2, 在子表发生 Insert,然后在父表上有update操作,然后再有一个会话对子表做insert

    重复上面的操作,不对session 1进行commit时,再开一个窗口(Session 5)对子表做insert

    这是我们看到,对于子表的insert语句被阻塞了。

    在Session 3中观察:

    这里我们看到: 1,当外键无索引时,对子表的insert操作,会造成对父表的更新操作的阻塞,该阻塞直到子表的insert事务结束,才自动释放。 2,如果对子表有insert操作,在这个insert所在事务没有commit之前,有对父表的update,那么接下来的对子表的inser会被阻塞

    测试3

    在测试2的场景上,将session 2和session 4中的对父表的update执行Ctrl+C,然后分别改为INSERT 和delete 父表(dept)的操作,观察一下 Session 4:

    Session 5 随之自动解锁,并报了正常的违反约束的错误:

    在session 2中执行delete 父表的操作:

    注意: 1,delete父表的操作被阻塞,依然是正在请求以LMODE=4的模式对子表(1062790 EMP)的TM锁 2,这里的sid 222中为非活动会话,当该回话执行了commit或者rollback后,这个Insert的“SQL*Net message from client”等待就会消失了。

    测试4: 在测试3的场景上,继续session 4中的对父表做insert 的操作,观察一下

    Session 4:

    这里我们看到,虽然Session 4执行的是对父表的insert,session 2执行的是对父表的 delete,他们的表现跟update的表现都是相同的。也就是说,对于子表的insert操作所在的事务没有完成前,对于父表的DML操作(INSERT/UPDATE/DELETE)都会因为不能获得对子表的TM锁而出现enq: TM – contention

    测试5: 在测试4的基础上,我们在Session 1对做commit,完成对子表的insert操作,然后观察其他session:

    Session 1:

    Session 4:对父表的insert插入操作随着session 1的commit 自动解锁:

    Session 2(SID 220):对父表的delete操作依然是hang的状态:

    也就是说,这里我们看到了,对父表的insert,阻塞了对父表的delete

    转载请注明原文地址: https://ju.6miu.com/read-1202560.html
    最新回复(0)