客户报告在做 job 导入的时候偶尔会碰到 ORA-00060 错误,客户端日志如下:
2020-11-23 12:22:15 (GMT+0100) [ERROR] : java.sql.SQLException: ORA-00060: deadlock detected while waiting for resource |
因为碰不到客户的生产环境,所以要了一下他们的服务端日志。一般来讲,ORA-00060 总是结对出现,然后我们根据这个错误抛出的程序调用栈,可以分别找到对应的两个线程,根据上下文及各自的 sql 语句不难得出数据库死锁的原因所在。
但本文案例有些特殊,属于二般情况。拿到服务端日志以后直奔 ORA-00060 的抛错调用栈而去,却发现只有一种线程栈,对应的 sql 语句也只有一种:
update jobother set jobother.allocatestatus='C' where job_unid in (142000000000397637,140000000000397301,140000000000397302,140000000000397303,140000000000397304,140000000000397543,140000000000397548,140000000000397638,140000000000397639,140000000000397640,140000000000397641,140000000000397642,140000000000397643)
走到这里,先头脑风暴一下。
带着这些疑问去问客户要了 trc 文件,直奔 Deadlock graph:
可见这是一个 Transaction Deadlock 型死锁。查找 session 425 的当前 sql:
update jobother set jobother.allocatestatus=:1 where job_unid in (142000000000405269,140000000000405066,140000000000405237,140000000000405264,140000000000405272,140000000000405275,140000000000405277,140000000000405279,140000000000405281,140000000000405283,140000000000405285,140000000000405287,140000000000405289,140000000000405291)
然后再找到 session 627 的当前执行 sql:
update jobother set jobother.allocatestatus=:1 where job_unid in (142000000000405269,140000000000405066,140000000000405237,140000000000405264,140000000000405272,140000000000405275,140000000000405277,140000000000405279,140000000000405281,140000000000405283,140000000000405285,140000000000405287,140000000000405289,140000000000405291)
对比之下,它们其实是一样的,头脑风暴 3 命中。这个线索很关键,这个分布式环境中 db 这一块的情况已经清晰明了。目前要做的事情则是找到接口介入的源头情况。带着它回过头去继续去分析服务端日志。两路并进,按图索骥:
两路互相结合参考分析,接着就发现确实有 5 个线程在执行同样的逻辑。重复请求?抑或是多线程误启了 5 个线程执行同样逻辑?带着这些疑问继续往前捋,最终发现是确实有 5 个文件需要导入,五个不同的任务线程分别同时执行导入,在执行到上述 sql 时造成死锁:
cargoMateFinishedQueue/ID:Defonds-Prod-App.hhh-37181-1606128682104-1:1:2189:1:1 cargoMateFinishedQueue/ID:Defonds-Prod-App.hhh-37181-1606128682104-1:1:2197:1:1 cargoMateFinishedQueue/ID:Defonds-Prod-App.hhh-37181-1606128682104-1:1:2200:1:1 cargoMateFinishedQueue/ID:Defonds-Prod-App.hhh-37181-1606128682104-1:1:2207:1:1 cargoMateFinishedQueue/ID:Defonds-Prod-App.hhh-37181-1606128682104-1:1:2213:1:1 |
经分析,这 5 个文件是同样的内容,导致问题的根本完全是上游服务器误生成了同样不同名的五个导入文件,并非是下游 job 导入服务器的接口幂等性问题。