原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处。

最近几周,发生过多起因为事务问题引起的服务报错。现象为数据库连接池连接占满,数据库连接长时间等待,最终导致请求线程hang住,服务大面积报错。这个时候,服务资源、数据库资源大量空闲,但就是进行不下去,影响是比较恶劣的。

谁来背锅?当然是架构师。因为这次所有的服务都活着,没运维什么事。

面试时,大家可能都会碰到关于事务相关的问题,升级版的可能是分布式事务的问题。在互联网行业中,一句马马虎虎的补偿事务就能蒙混过关,毕竟都是些短小精悍的接口。

但在很多企业级应用中,这行不通。我们必须直面惨淡的现实。

为什么要用长事务?

在许多业务非常复杂的后台系统,经常频繁操作DB,为了保证数据的一致性,能够在出错时回滚数据,通常会使用事务。

就拿最简单的单机数据库事务来说。

在事务操作期间,如果持续时间过长,只有等事务结束之后,DB连接才会释放,此类长时间占用DB连接的事务操作,称为长事务。一旦外部有大量请求,并发调用此操作,那么将会有大量的DB连接被持有而没有被释放掉,直到连接池爆满。

这个时候,如果有其他请求到来,那十有八九是以失败告终。

也就是说,连接资源被少数长事务操作占用。在这种情况下,即使是最简单接口查询,都不能够正常进行。

几粒老鼠屎,坏了一锅粥。

一些魔幻的反应

当你去排查这种问题的时候,可能会陷入僵局。jstack显示,多数请求其实是阻塞在tomcat的线程池上,而且是一些访问速度非常快的请求被阻塞。

比如,tomcat的200个线程,有180个阻塞在耗时不到1ms的/status接口上。

很多人就一脸懵逼。经验失灵。

jstack此时的输出结果,欺骗了我们。真正造成阻塞的,是那额外的20多个线程。

有哪些改善?

保证事务的短小是一个基本要求,包括但不限于:

应控制慢查询的调用频率,尽量减少慢查询。很多情况下,这条规则是自欺欺人的,需要业务做一些妥协。

事务内不应包含任何RPC调用,减少事务的粒度。通常,一些RPC调用,包括其他非事务资源的调用,耗时非常不可控。如果把它们也纳入事务的范围之内,势必会加剧资源的占用。事务内不应包含其他容易超时或者长时间阻塞的服务,如HTTP调用、IO操作。

次优先级服务如消息队列,不应该放在事务内,避免因为消息队列不可用引起的服务不可用。给类似消息队列的组件,设置一个合理的超时时间的非常有必要的,否则它就会一直等在那里。但即使是这样,也尽量不要把它们纳入到事务操作之内。

跨库、跨类型(如Redis),不应该放在同一事务中,可避免交叉影响。

你可以看到上面的这些描述,有些和我们所追求的数据一致性是相悖的。这不奇怪,依然是CAP原理的权衡。有些业务选择的是宁可卡死不再响应,也不能进入异常数据;有些则首先让业务运行下去,脏数据会通过补偿事务进行修正。

一切看你的选择。

设计总有人背锅,补偿总有人做出牺牲。

解决方式

那么如何来快速解决大事务造成的服务不可用问题呢?

除了扩容,其实是无解。重启大法也不见得好用。因为被阻断的请求,会以更凶猛的态势再次来袭。

你可能会想到调大连接池的大小。但在实践中得知,也不好用,大事务请求会迅速将连接池占满。

但我们可以提前进行防御。

以Spring为例,事务的使用方式大多数是使用@Transactional注解来控制的,或者是声明式事务方式。我建议以以下方式进行预防和发现:

1) 重新扫描或者Review业务代码,排查事务中是否有以上提到的各种情况。然后将除DB操作外的其他操作移动到事务之外。

2) 每个事务操作都给予足够重视,对于执行复杂度和时间复杂度不确定的事务,添加超时报警,及时发现引起的原因。

同时,还需要加强监控,辅助进行问题排查。

1)  业务可以考虑定时将数据库连接池的信息进行打印,通过看日志的方式进行初步排查。

2) 使用jstack查询执行栈,找出阻塞的点。

3) 排查并联系下游服务,找出主要原因

xjjdog倾向于使用监控快速发现问题。如图,通过连接池监控,可以看到数据库连接池连接数长时间保持在高位不释放,同时等待的线程数急剧增加。发生此种现象多数可以考虑是否是以上原因引起。

发生问题时,应及时(多次)使用jstack定位到线程的阻塞位置,然后排查下游服务是否有问题,或者是否存在慢查询。

最好的情况是服务已经进行了对代码的梳理,那么引起的原因大概率只剩下了慢查询。针对慢查询,druid数据库连接池,提供了sql的聚合,能够查看是每一类查询语句的具体执行情况。如图,短时间内SQL请求飙升,最大执行时长上升,连接池占满:

具体是哪一句SQL所引起的,一目了然。

End

长事务问题的危险级别属于高危型,通常会造成严重的后果,可以通过观察监控,防范于未然。

最优的解决方式,当然是业务模型的改进。但这东西第一涉及到开发成本,第二涉及到跨部门协作。

出钱的老板,无法听懂你这些梦话。

在一些公司内部,这两者都是让人抓狂的事情,还不如痛痛快快背个锅,来得实在。

作者简介:小姐姐味道  (xjjdog),一个不允许程序员走弯路的公众号。聚焦基础架构和Linux。十年架构,日百亿流量,与你探讨高并发世界,给你不一样的味道。

有道无术,术可成;有术无道,止于术

欢迎大家关注Java之道公众号

好文章,我在看❤️

又一批长事务,P0故障谁来背锅?相关推荐

  1. 增加自增列 耗时长_又一批长事务,P0故障谁来背锅?

    原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处. 最近几周,发生过多起因为事务问题引起的服务报错.现象为数据库连接池连接占满,数据库连接长时间等待,最终导致请求线程hang ...

  2. SpringBoot - 优雅的处理【长事务】

    文章目录 Pre What How 方法一 编程式事务 使用@Transactional 又能避免产生长事务 方法一 方法二 Pre SpringBoot - 实践阿里巴巴[Manager 层_通用业 ...

  3. 为什么不要使用长事务

    比如,在某个时刻(今天上午9:00)开启了一个事务A(对于可重复读隔离级别,此时一个视图read-view A也创建了),这是一个很长的事务-- 事务A在今天上午9:20的时候,查询了一个记录R1的一 ...

  4. oracle 长事务 逻辑日志,goldengate中长事务引起的问题

    一.问题描述: 2013年4月14日中午12点左右生产环境执行数据库版本升级期间根据需要停止XX1库和XX2库OGG 同步抽取进程时遇长事务,无法用正常命令停止,执行 forcestop 后重启进程报 ...

  5. mysql什么是长事务

    1.什么是长事务 首先我们先要知道什么是长事务,顾名思义就是运行时间比较长,长时间未提交的事务,也可以称之为大事务.这类事务往往会造成大量的阻塞和锁超时,容易造成主从延迟,要尽量避免使用长事务.

  6. mysql长事务慢查询解决方案_MySQL : 如何监控和处理慢查询与长事务 ?

    什么是慢查询.长事务 ? 慢查询 是指一条 SQL 的执行时间太长.比如在一个有100w条数据的表中,查询一条数据时未命中索引,从而通过全表扫描查询数据,这个查询会耗时很长.这就是一个 Long SQ ...

  7. 程序员捅了个P0故障,公司股价反而涨了10%!

    ‍ ‍今年6月,有一次大范围的全球知名网站宕机,国内的网民感知可能没那么强烈,但是在国外,很多知名网站都受到了波及. 本次大规模宕机时长长达一小时,受到影响的网站有谷歌.Twitter.亚马逊.eBa ...

  8. mysql 长事务查询_MySQL长事务详解

    前言: 『入门MySQL』系列文章已经完结,今后我的文章还是会以MySQL为主,主要记录下近期工作及学习遇到的场景或者自己的感悟想法,可能后续的文章不是那么连贯,但还是希望大家多多支持.言归正传,本篇 ...

  9. informix长事务的处理方式

    一.登陆数据库服务器,切换到informix用户 infodb% su - informix Password:  Sun Microsystems Inc.   SunOS 5.8       Ge ...

最新文章

  1. 斯坦福NLP团队发布最新自然语言处理Python库
  2. 解决linux下oracle进入sqlplus环境中后退键显示^H、上下键无效与ctrl+l无法清屏等问题【weber出品必属精品】...
  3. docker 占用磁盘空间清理 无用数据卷删除
  4. MPLS服务采购面临哪些挑战?
  5. axis2 调用webservice
  6. 交换机的基本功能和应用就是集中连接网络设备
  7. 编译器入门 语法分析器 java_从零开始写个编译器吧 - Parser 语法分析器
  8. linux添加中文字库主线任务,Linux 添加中文字体库
  9. 将表达式树转换成中缀表达式☆
  10. android Gallery实现异步加载网络图片
  11. 随笔 | 读《写给年轻程序员的思考书》ii
  12. puppet详解(六)——exec资源详解
  13. 开源SignalR-Client-CPP使用总结
  14. 页眉设置为章节名(WPS)
  15. zblog php 分类页,zblog怎样实现不同分类页调用不同页面模板和样式
  16. Linux进程调度器的设计--Linux进程的管理与调度(十七)
  17. JSP完成添加商品时的图片上传
  18. 1994年颁布了计算机安全,1994年2月18日,我国颁布了( ),这是我国的第一个计算机安全法规,是我国计算机安全工作的总体纲领。...
  19. 存储连接应用服务器简单入门
  20. 绝望而沉重的爱·《致我们终将逝去的青春》

热门文章

  1. php tp写构造函数,详细介绍ThinkPHP中类的构造函数_construct()与_initialize()的区别
  2. wap打包 本地化 hbuilder_秋收接近尾声 冰城开启秸秆打包、秋整地
  3. C++11 并发指南四(future 详解三 std::future std::shared_future)
  4. C/C++劫持技术(函数劫持、dll注入、动态库注入、HOOK)
  5. 制作cab文件(Windows自带的makecab)
  6. Java 线程实例一(查看线程是否存活、获取当前线程名称、状态监测、线程优先级设置、死锁及解决方法、获取线程id、线程挂起)
  7. eclipse常用设置及调试快捷键
  8. NameError: name 'file' is not defined
  9. 获取windows所有端口
  10. c# 轻量级ORM框架 实现(一)