我的工作因死锁而失败。同时以API模式并行地将数据插入Oracle表。在插图之前,在表上发生更新。既然插入操作不锁定任何其他行,那么死锁的可能原因是什么?增加insert的提交数量会有帮助吗?
goucqfw61#
在这样的场景中,有几种方法会导致死锁。1.插入物不能取出锁是不正确的。它以防止任何排他表锁的模式锁定表,如果任何列上有FK,它将锁定父表中的父行,以防止它们被删除。1.像任何其他DML一样,插入必须在块中保存ITL(感兴趣的事务列表)插槽,并且如果它插入到预先存在的块(非追加模式)中,则可能缺少ITL插槽和用于创建更多的空闲空间,这可能导致它等待其他DML(如那些更新),而这些DML又可能由于插入而在另一个块中发现自己处于类似的情况。因此,您可能会以循环锁定的情况结束,Oracle将检测并失败一个。1.如果在Exadata中使用HCC(混合列式)压缩,而没有ACO许可证,则每个压缩单元(CU)只有一个锁定位,而不是每行一个。并发更新(无论是通过单独的线程还是使用PDML)几乎肯定会因此而在它们之间死锁。1.您的insert可能使用直接路径模式,这需要一个排他的表锁,使其与同时对该表运行的其他DML不兼容。如果在表上持有任何类型锁的其他会话同样被插入阻塞,则存在循环。1.如果您的更新将条目插入到索引中,它们同样需要索引叶块中的ITL条目。您可以使用上面针对表块ITL所解释的另一个过程来进入相同的情况。1.如果更新是更新作为唯一键的一部分的列,则Oracle将不允许可能创建重复项的插入,直到事务完成。1.您可以在表上设置一个触发器,将这些更新记录在其他某个表中,并尝试记录插入。如果该日志记录的粒度与主表的粒度不同,则两者最终都将更新相同的日志记录行,并且再次出现阻塞。如果我继续头脑 Storm ,我可能会想出更多的场景。关键是,有很多方法可以阻止更新插入,如果形成循环链,任何阻塞都可能导致死锁。您必须确定死锁的实际原因才能知道如何修复它。检查由死锁条件生成的跟踪文件,并使用它来标识链。修复将取决于到底发生了什么,这将要求您将跟踪文件与您对这些进程正在运行的实际代码的了解进行比较。
1条答案
按热度按时间goucqfw61#
在这样的场景中,有几种方法会导致死锁。
1.插入物不能取出锁是不正确的。它以防止任何排他表锁的模式锁定表,如果任何列上有FK,它将锁定父表中的父行,以防止它们被删除。
1.像任何其他DML一样,插入必须在块中保存ITL(感兴趣的事务列表)插槽,并且如果它插入到预先存在的块(非追加模式)中,则可能缺少ITL插槽和用于创建更多的空闲空间,这可能导致它等待其他DML(如那些更新),而这些DML又可能由于插入而在另一个块中发现自己处于类似的情况。因此,您可能会以循环锁定的情况结束,Oracle将检测并失败一个。
1.如果在Exadata中使用HCC(混合列式)压缩,而没有ACO许可证,则每个压缩单元(CU)只有一个锁定位,而不是每行一个。并发更新(无论是通过单独的线程还是使用PDML)几乎肯定会因此而在它们之间死锁。
1.您的insert可能使用直接路径模式,这需要一个排他的表锁,使其与同时对该表运行的其他DML不兼容。如果在表上持有任何类型锁的其他会话同样被插入阻塞,则存在循环。
1.如果您的更新将条目插入到索引中,它们同样需要索引叶块中的ITL条目。您可以使用上面针对表块ITL所解释的另一个过程来进入相同的情况。
1.如果更新是更新作为唯一键的一部分的列,则Oracle将不允许可能创建重复项的插入,直到事务完成。
1.您可以在表上设置一个触发器,将这些更新记录在其他某个表中,并尝试记录插入。如果该日志记录的粒度与主表的粒度不同,则两者最终都将更新相同的日志记录行,并且再次出现阻塞。
如果我继续头脑 Storm ,我可能会想出更多的场景。关键是,有很多方法可以阻止更新插入,如果形成循环链,任何阻塞都可能导致死锁。您必须确定死锁的实际原因才能知道如何修复它。检查由死锁条件生成的跟踪文件,并使用它来标识链。修复将取决于到底发生了什么,这将要求您将跟踪文件与您对这些进程正在运行的实际代码的了解进行比较。