一次 select for update 的悲观锁使用引发的生产事故
1.事故描述
本月 8 日上午十点多,我们的基础应用发生生产事故。具体表象为系统出现假死无响应。
查看事发时间段的基础应用 error 日志,没发现明显异常。查看基础应用业务日志,银行结果处理的部分普遍很慢,大都在十分钟以上。
2.AWR 报告
向 DBA 要了一下那个时间段的 AWR 报告,发现以下三个地方有些异常:
2.1.CPU 利用率过高
如上图所示,CPU利用率:1883.25分钟DB时间/(16核心*119.45分钟采样时间段时间) = 98.54%,CPU 利用率过高。
2.2.行锁等待严重
如上图"Top 5 Timed Events"所示,行锁等待占用了 80% 的 CPU 时间,基本可以确定它就是造成本次生产事故的直接元凶。
所以我们直接跳到"Wait Events"排行榜:
这说明了什么?在本次 AWR 报告的 09:00:45 - 11:00:12 大约 119.45 分钟的时间里,行锁等待的时间为 99974 秒,合 1666.23 分钟!
2.3.悲观锁慢查询严重
那么是什么操作造成行锁等待如此之严重呢?如此严重的行锁等待,慢查询统计列表里应该很突出地指示出来,我们直接跳到"SQL ordered by Elapsed Time"慢查询排行榜:
果不其然,两个小时的时间内,id 为 3x0hq0nmj6a93 的那条 sql 查询耗时 93158 秒(合 1552.63 分钟),平均每条执行时间为 306.44 秒(合 5.11 分钟),占用了 80% 以上的的 CPU。
让我们来看看这条 sql 的真面目吧:
select ORD_BILLNO, ORD_PRDCODE, ORD_CRCODE, ORD_MERBILLNO, ORD_PRETIME, ORD_DOTIME, ORD_MERTIME, ORD_MERCODEFROM, ORD_TYPEFROM, ORD_MERCODETO, ORD_TYPETO, ORD_ACCCODEFROM, ORD_ACCCODETO, ORD_AMT, ORD_STATUS, ORD_ATTACH, ORD_UPDATETIME, ORD_PRODUCT, ORD_REFUNDED, ORD_REFUSE, ORD_PREIP, ORD_ENDIP, ORD_BILLEXPTIME, ORD_DIRECTLY, ORD_SYSCODE, ORD_BRCCODE, ORD_SRCCODE, ORD_PAYEDAMT, TRD_CODE, RESV1, RESV2, RESV3, ORD_PRDCODE_OLD, TRD_CODE_OLD, ORD_USERACCTYPE from T_PSFP_ORDER_TMP where ORD_BILLNO = :1 for update
这是一条 select for update 数据库悲观锁查询语句,因为指定订单号,所以会锁定 T_PSFP_ORDER_TMP 表的某一条语句,印证了 2.2 中的结论。
3.代码分析
调用上述 sql 的代码:
Order tempOrder = orderTempDao.selectOrderByPrimaryKeyForUpdate(verifyResult.getBillNo());
该业务代码先拿到该临时交易的锁,然后继续处理后续相当繁琐业务逻辑,中间还有大量的其它数据库操作,因为是声明式事务处理,所以在整个业务逻辑执行结束之后才会 commit,这段时间内如果还有其它 session 想拿这个行锁,就必须等到这一系列业务逻辑执行完毕。
正常情况下,这个逻辑是没问题的,但是在高并发的时候,这些业务逻辑受到 CPU 及网络等资源的限制可能会被拖慢,业务逻辑处理慢倒没什么,可怕的是数据库被拖慢,反过来又影响这些业务逻辑,形成一个滚雪球的效应,直至系统故障。
4.解决方案
技术中心不允许使用 select for update 悲观锁,尤其是在大量业务逻辑的情况下,至于原有业务逻辑可以使用其他处理方案进行替代。如必需使用 select for update,须与架构部讨论后才可使用。
最后,关于Oracle AWR 报告的生成和分析请参考博客《Oracle AWR 报告的生成和分析》。
一次 select for update 的悲观锁使用引发的生产事故的更多相关文章
- mysql 多列唯一索引在事务中select for update是不是行锁?
在表中有这么一索引 UNIQUE KEY `customer_id` (`customer_id`,`item_id`,`ref_id`) 问1. 这种多列唯一索引在事务中select for upd ...
- Insert into select语句引发的生产事故
前言 Insert into select请慎用.这天xxx接到一个需求,需要将表A的数据迁移到表B中去做一个备份.本想通过程序先查询查出来然后批量插入.但xxx觉得这样有点慢,需要耗费大量的网络 ...
- Mysql锁机制--乐观锁 & 悲观锁
Mysql 系列文章主页 =============== 从 这篇 文章中,我们知道 Mysql 并发事务会引起更新丢失问题,解决办法是锁.所以本文将对锁(乐观锁.悲观锁)进行分析. 第一部分 悲观锁 ...
- [MySQL] 行级锁SELECT ... LOCK IN SHARE MODE 和 SELECT ... FOR UPDATE
一.译文 翻译来自官方文档:Locking Reads If you query data and then insert or update related data within the same ...
- SQL Server 锁机制 悲观锁 乐观锁 实测解析
先引入一些概念,直接Copy其他Blogs中的,我就不单独写了. 一.为什么会有锁 多个用户同时对数据库的并发操作时会带来以下数据不一致的问题: 1.丢失更新 A,B两个用户读同一数据并进行修改,其中 ...
- Spring Boot 整合 MyBatis 实现乐观锁和悲观锁
本文以转账操作为例,实现并测试乐观锁和悲观锁. 完整代码:https://github.com/imcloudfloating/Lock_Demo GitHub Page:http://blog.cl ...
- MySQL学习之——锁(行锁、表锁、页锁、乐观锁、悲观锁等)
转载. https://blog.csdn.net/mysteryhaohao/article/details/51669741 锁,在现实生活中是为我们想要隐藏于外界所使用的一种工具.在计算机中,是 ...
- MySQL锁(行锁、表锁、页锁、乐观锁、悲观锁等)
锁,在现实生活中是为我们想要隐藏于外界所使用的一种工具.在计算机中,是协调多个进程或县城并发访问某一资源的一种机制.在数据库当中,除了传统的计算资源(CPU.RAM.I/O等等)的争用之外,数据也是一 ...
- MySQL中锁详解(行锁、表锁、页锁、悲观锁、乐观锁等)
原文地址:http://blog.csdn.net/mysteryhaohao/article/details/51669741 锁,在现实生活中是为我们想要隐藏于外界所使用的一种工具.在计算机中,是 ...
随机推荐
- android4.1 Wifi 浅析
简单分析下wifi相关类,首先了解几个主要概念 AsyncChannel 简单理解: AsyncChannel,就是借助Messenger 机制,让两个不同的handler之间进行通信. AsyncC ...
- Qscintilla2编译使用
Qscintilla2的下载地址: https://github.com/josephwilk/qscintilla https://riverbankcomputing.com/software/q ...
- Ext.Net中如何获取组件
我们在编写函数function的时候,常常需要用到页面上的组件.这时候就需要调用组件. 在Ext.net中,调用组件可以用.App.ID.(ID指的是想要调用的组件的ID). 例如: 我写一个函数需要 ...
- Linux之JDK在线安装及配置
1.查找java相关得列表 yum -y list java*2.在线安装 yum -y install java-1.6.0-openjdk*3.查看安装目录 ls -l /usr/lib/jv ...
- LevelDB速记
LevelDb的基本结构如下: 由六大部分组成: 一.MemTable,用户写入和读取的直接对象, 二.Immutable MemTable,用户状态写入的对象写满的MemTable之后会转为Immu ...
- [剑指Offer] 21.栈的压入、弹出序列
题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序 ...
- 【心情】HNOI2018游记
Day 0. 全机房的人好像都在做题.然而下午是社团节的游园会,身为社干的我风风雨雨在外面各种搬凳子搬椅子换场地招待外校同学……就这样我好像什么都没有复习. 晚上就一起去酒店了.大概因为是高一的缘故, ...
- 【题解】ZJOI2007报表统计
洛谷传送门 主要思路大概也是差不多的,对于两种询问分别用线段树与平衡树来维护. 1.MIN_SORT_GAP:显然平衡树简单操作,来一发前驱.后继即可. 2.MIN_GAP:这一个我用的是线段树:可以 ...
- 你试过不用if写代码吗?
我在教新手编程时,喜欢给他们一些小小的挑战,比如:不使用if语句(或者三元运算符.switch语句等)解决一些编程问题.这样做有什么意义吗?事实上,它可以迫使你从不同的角度寻找解决方法,也许可以找到更 ...
- BZOJ2286 [Sdoi2011]消耗战 【虚树 + 树形Dp】
2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 4261 Solved: 1552 [Submit][Sta ...