接下任务

这是平凡的一天,但是今天,我接到了一个艰巨的任务!
领导给我发信息了!
财务系统经常出现数据库锁表,最近出现频率特别高,已长达有一年之久。希望我能解决掉这个巨大的隐患!

当时,我一头雾水,这个系统从没接触过,代码写的怎样,数据库设计的怎样,具体业务逻辑是怎么,我都不知道。但是,领导既然找我处理,必是遇到了难过的坎,我必须解决!

于是,脑子中立即浮现了能产生锁表的所有情况:
1)事务开启后,没有提交或回滚
2)并发竞争相同的数据库资源,造成相互等待
3)还有其他情况吗?

当天下午,我动手了!
拉取了所有的代码,折腾了好一会儿,本地运行起来了,开始熟悉代码。
这是个前后端分离的项目,后台通过springMVC暴露restfull接口,前端是AngularJs。

尝试解决

从代码上看不出明显的错误,还得从日志着手,先看看日志吧。
惊喜来了,服务器上怎么找不到日志,这下懵了!
原来是log4j日志配置有误,导致服务器上根本就没记录日志文件,于是顺手把日志问题解决了。
第二天,终于可以看见系统运行日志了。

日志输出太少,看不到有用的信息,在锁表的时候,只看见事务超时了,但是多数是卡在查询事务上,难道是查询太慢了吗?不可能啊,查询太慢的话,顶多也就系统慢一点而已,不可能造成锁表。

好吧,继续看代码!
又一惊喜!后台怎么没使用spring注解事务,xml配置事务也没有!难道这个系统就没使用事务?
咨询项目老员工得知,后台使用的是手动事务。在需要的地方手动开启事务,然后执行完成后,提交事务,如果抛异常或执行失败了,就回滚事务。

“这什么思想,为什么要这么做?”。
老员工无奈的表示:“我也不知道,这项目做的时候,我还没来呢!”
“我们把手动事务去掉,改成自动事务吧,让spring来管理事务,肯定比手动管理要靠谱”
“可以啊,但是项目中已经有非常多的地方这么用了,改起来会不会有风险?”
我心想,你说的也有道理,财务系统比较重要,既然系统已经运行这么长时间了,还是不宜大动干戈,稳扎稳打会比较好点,毕竟我也没有明确的证据证明就是手动事务造成的。
好的,历史遗留问题!

小有收获

死马当活马医,先把眼前明显的性能问题解决了再说!
加缓存吧!我用了guava,给所有的配置数据加上了一层缓存。这个改动花了不少时间,每次需要和需求人员确定后才能改动。
期间还发现了ibatis(你没看错,这里用的是ibatis,不是mybatis)嵌套查询老是会出现事务超时。
全部改掉吧!将这些嵌套查询,全部改成service里面再查询一次,如果是配置数据就改成缓存查询,我就不信还会查询超时。

查询超时没有了,系统稳定了一些,锁表问题有所改善!
从之前的每天一大早就锁表,一天锁表好几次;变成现在每天中午左右锁表,一天锁表一两次。
总算有所安慰,但是问题还未解决,前面的改动治标不治本!

被锁的表仍然千奇百怪,但是有几个表特别频繁被锁。
先研究这些重点表吧!果然有收获,从代码中发现,有个service方法,前后多次修改了同一张表,还有可能是同一条记录。这在并发情况下,完全满足锁表条件。
好的,就是你了,改掉吧,拆分成两个事务!
第二天,没锁表了。问题会不会就这样解决了呢!我心里也在打鼓。不大可能吧,锁的表又不止这个!
“这次要是解决了,我到静安寺烧个香!”同事冒出调侃的声音,显然也略显无奈!
果然,到第三天下班的时候,群里消息来了“看看是不是锁表了,系统又不能用了”
真的锁表了,噩耗还是来了!逃避是不可能了,勇敢面对现实吧。

天道酬勤

事到如今,没有更好的办法,只能看代码,一定是手动事务使用不当导致的!
搜索了所有使用手动事务的地方,我一行行代码看过去(应该有100多处使用手动事务,有的方法还特别长)。
皇天不负苦心人!我发现有两个地方事务开起来,没有提交或回滚,这里要是调用了,锁表是必然的!
又过一天,我如约期待锁表的消息,但主观上我又不希望得到消息,希望问题就此解决。下午6点多,消息来了!又是噩耗!
好吧,换掉c3p0链接池,这个连接池不稳定,Druid会好很多,还有监控可以方便查看连接池情况!
当天晚上,我们换了连接池!
“我今天晚上到静安寺烧个香吧,希望这次能够解决!”同事又胆颤的冒了一句。
可惜,当天晚上发布失败了,可能是代码没合并好。先回滚代码吧,今晚发布取消。
“你去晚了,应该一下班就去烧香”又一同事调侃了一句。
第二天,我开个新的代码分支,本地合并好代码提交了,今晚继续发布。
终于发布成功了!连接池终于换了,但也只是个自我安慰,我又怎么会不清楚锁表问题和c3p0到底会不会有关系。

问题解决

又隔几天,我惊喜的发现,现在锁表非常聚焦,基本就是那两三张表了。
找到了!和这些表有关系的,有可能造成锁表的就这两个方法了,安排两个测试人员在demo环境做并发试试吧。
demo环境锁表了!在界面上同时点击之后产生的。顿时群里爆炸了!
这是质的飞跃!找到问题了,距离解决也就不远了!

我左看右看,上看下看,来回看了好几遍。这代码到底有什么问题呢!
眼尖的同事指出:“这个地方有个判断,直接返回了,没有提交或回滚事务,应该是这里导致的。”
恍然大悟!肯定是这个问题,之前一直关注事务打开后,在最后有没有提交或回滚,而忽略了,在中间也有可能有问题!
改进之后,继续测试,demo环境没锁表了。问题解决了!
但是别高兴太早,直觉告诉我,应该还有问题!既然这个方法有这种问题,系统中别的地方应该有类似的问题!
于是,我又搜索了所有的手动事务代码,一行行看看过去!又找到了四个类似的问题,这下应该算是解决了!
第二天,我安静的等待消息,锁表的消息。
群里有人@我,“帮忙看一下是不是锁表了”,老天爷真会开玩笑,难道还有问题!
“没有锁表,有惊无险”,看一下日志,是有个异常导致的!这是业务异常,不是锁表!
第一次看见业务异常我是这么开心!(这是什么思想呢!)

峰回路转

之后的连续好几天系统正常运行!大家都欢呼雀跃,心想这个鬼问题终于解决了!
但是,好景不长。
到了,第七天,群里来消息了:“看看有没有锁表,系统不能用了”
这是早上10:30,星期五,本来以为可以好好度个周末,可是就像有人狠狠地抽了我一个大嘴巴,瞬间精神了。
真的锁表了,先解锁了,让用户能用再说。
查看日志,发现从10:19开始,有非常多的慢sql日志,我下意识的问了一句:“10:19有没有动过数据库,感觉系统慢了很多”,群里议论了一番,没人动过。
当时我一头雾水,又审查了两遍事务代码,所有的事务隐患已经全部改掉了,不可能再有事务问题,这叫我怎么办呢!
没过多久,大概半个小时时间,系统又出问题了。感觉自己也快奔溃了,不能让这事情继续发生,我连上服务器,感觉有点不对劲,好像比平时慢很多。
服务器CPU100%了,事务锁表不可能造成这个问题的,一定是其他问题,比如死循环或者大数据查询等。
还是看看日志吧!有GC频繁回收异常,这是内存不够用啊,有线索了,问题马上就能找到!
仔细往回翻日志,我发现有个附件表的全表查询,这是一个千万级记录的超级大表,全表查询必定撑爆内存,好的,肯定是这个问题!
回头看10:19分的日志,果然,当时也有一个一样的sql语句!问题确定了。
整个人都放松了,终于搞清楚了!

经验总结

这个任务从我接手到解决,经历了近三个月,主要做了如下改动:
1)修改系统log4j日志
2)增加许多配置数据缓存
3)修改ibatis嵌套查询
4)修改所有未关闭的事务代码
5)大表全表查询,导致服务器内存不足,进而导致整个服务器变慢

总结下来,关键问题还是如刚开始的预测“问题肯定出在事务上”,但是要找到问题并解决问题,真要历尽劫难,甚至开始怀疑自己的常识!

问题千奇百怪,总有解决办法,过程千辛万苦,又有几人能懂!

记一次数据库锁表处理心路历程相关推荐

  1. mysql update 锁_Mysql心路历程:两个”log”引发的”血案”

    今年开始,自己开始修炼储存与消息相关的技术"内功",想着在当下的开发工作与未来的路途发展中,这两大块是无论如何都无法避开的,所以就开始加强:Mysql.redis与Mq.Mysql ...

  2. oracle库锁表处理,oracle 数据库锁表处理 ORA-00031

    今日执行删除业务系统表中的一部分待修复数据中,出现锁表情况,具体如下: (1) 备份待删除表中的待删除数据 create table  t_renewal_stats_data_20120712 ta ...

  3. 记可视化项目代码设计的心路历程以及理解

    前言: 这篇文章包含了我这段时间的对代码的理解以及设计的反思,又到了否定以前的代码尝试去做更好的设计与想法的时候.从前引以为傲,自觉还行的代码如今看来,尽管仍然有它的可取之处,但有更多的需要精进的地方 ...

  4. 从开发者到讲师的心路历程

    写在前面:博主是一只经过实战开发历练后投身培训事业的"小山猪",昵称取自动画片<狮子王>中的"彭彭",总是以乐观.积极的心态对待周边的事物.本人的技 ...

  5. 【回眸】Study with me!计算机二/三 级(物联网)刷题的心路历程

    计算机二级(物联网)刷题的心路历程 1.NB-IoT的具体应用不包括__________. A.智能水表 B.共享单车 C.智慧门锁 D.高清视频监控 这题比较难的地方就在于NB-IoT是什么东西,笔 ...

  6. 【博客话题】我的linux心路历程

    2011年的某一天,程程同学在QQ上跟我说"linux 20周年了,有没有关于linux话题的好点子",回神一想,是啊,linux都20周年了,是应该搞一个有意义的话题了,我就建议 ...

  7. 关于代码效率提升的方法心路历程(购物车)

    关于代码效率提升的方法心路历程(购物车) 给为园友们,大家好,最近一直解决执行提速,分析老代码的逻辑并提出优化方案,在这个过程中发现了很多不好的习惯,导致很多程序逻辑执行效率低下,现在将其总结一下,如 ...

  8. RadHat 6 系列心路历程、新功能及变化

    RadHat 6.0系列心路历程 首先最大的改变是配置内核为2.6.32  .默认文件系统升级为为ext4(比ext3速度更快,可达16TB).其它可用文件系统附加件包括XFS(可扩展到100TB)和 ...

  9. 数据库分表处理设计思想和实现

    数据库分表处理设计思想和实现 一.概述 分表是个目前算是比较炒的比较流行的概念,特别是在大负载的情况下,分表是一个良好分散数据库压力的好方法. 首先要了解为什么要分表,分表的好处是什么.我们先来大概了 ...

最新文章

  1. 探索“老药新用”最短路径:亚马逊AI Lab开源大规模药物重定位知识图谱DRKG
  2. python散点图拟合曲线-python 绘制拟合曲线并加指定点标识的实现
  3. 一些非常实用的JSON 教程
  4. 【数学建模】MATLAB应用实战系列(九十二)-教你怎么挑对象,层次分析法应用案例(附MATLAB代码)
  5. java反射模式_Java反射机制详解
  6. Java EE中的RESTful计时器
  7. python数据获取手段包括哪些_python开发应用-本地数据获取方法
  8. ruby array_Ruby中带有示例的Array.fill()方法(1)
  9. php中命名空间、面向对象、访问控制、接口
  10. LightOJ1234 Harmonic Number
  11. mysql事务控制(xa分布式事务)和锁定语句_MySQL的SQL语句 -事务性语句和锁定语句(7)- XA 事务...
  12. C/C++编程语言中volatile关键字介绍
  13. 标准机器学习数据集的最佳结果
  14. win10下安装Mapx5.0进行MFC开发的方法
  15. 浅谈软件项目验收(转)
  16. TPLinker 实体关系抽取代码解读
  17. npm 版本更新指令
  18. itextpdf简单使用 制作豆瓣日志pdf
  19. 啦啦啦!令人激动的国庆小长假快要到来啦!大家是否都有出游的打算呢?
  20. github 私有化部署_项目私有化部署

热门文章

  1. matlab数据点怎么积分,matlab 数值积分方法
  2. python抢课脚本 验证码_用Python实现模拟登录正方教务系统抢课
  3. Hystrix Turbine
  4. 基于百度地图画出物流起始线路
  5. Android 隐藏LinearLayout
  6. matlab b-spline
  7. 面试官:super()和super(props)有什么区别?
  8. WebRTC入门与实战 --- WebRTC原理与架构
  9. IBM花300万美元打造互联网三维虚拟紫禁城
  10. c++与java的应用区别