精华内容
下载资源
问答
  • 财务系统经常出现数据库锁表,最近出现频率特别高,已长达有一年之久。希望我能解决掉这个巨大的隐患! 当时,我一头雾水,这个系统从没接触过,代码写的怎样,数据库设计的怎样,具体业务逻辑是怎么,我都不知道...

    接下任务

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

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

    于是,脑子中立即浮现了能产生锁表的所有情况:
    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)大表全表查询,导致服务器内存不足,进而导致整个服务器变慢

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

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

    展开全文
  • 首先我们先了解下什么是数据库锁, 锁是事务对某个数据库中的资源(如和记 录)存取前,先向系统提出请求,封锁该资源, 事务获得锁后,即取得对数据的控制权,在事务释放它的锁之前,其他事务不能更新此数据。...

     

    锁的概念:

    首先我们先了解下什么是数据库锁,

    锁是事务对某个数据库中的资源(如表和记 录)存取前,先向系统提出请求,封锁该资源,

    事务获得锁后,即取得对数据的控制权,在事务释放它的锁之前,其他事务不能更新此数据。当事务撤消后,释放被 锁定的资源。 

     

    数据库锁的分类:

    共享锁:又叫S锁或者读锁,加了共享锁的数据对象可以被其他事务读取,但不能修改, 通常是该数据对象被读取完毕,锁立即被释放

     

    排他锁:又叫X锁或者写锁,当数据对象被加上排它锁时,一个事务必须得到锁才能对该数据对象进行访问,一直到事务结束锁才被释放。 在此之间其他的事                 务不能对它读取和修改。

     

    死锁:

    死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。

    这些永远在互相等待的进程称为死锁进程

     

    产生死锁的必要条件:

    1、互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
    2、不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
    3、请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
    4、循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。

    死锁产生的原因:

    1) 系统资源的竞争

    通常系统中拥有的不可剥夺资源,其数量不足以满足多个进程运行的需要,使得进程在 运行过程中,会因争夺资源而陷入僵局

    2) 进程推进顺序非法

    进程在运行过程中,请求和释放资源的顺序不当,也同样会导致死锁。例如,并发进程 P1、P2分别保持了资源R1、R2,而进程P1申请资源R2,进程P2申请资源R1时,两者都 会因为所需资源被占用而阻塞。

    3)信号量使用不当也会造成死锁。

    进程间彼此相互等待对方发来的消息,结果也会使得这 些进程间无法继续向前推进

     

    如何避免死锁

    三种用于避免死锁的技术:

    1)加锁顺序:

    一个线程需要一些锁,那么它必须按照确定的顺序获取锁。它只有获得了从顺序上排在前面的锁之后,才能获取后面的锁。

    例如,线程2和线程3只有在获取了锁A之后才能尝试获取锁C(获取锁A是获取锁C的必要条件)。因为线程1已经拥有了锁A,

    所以线程2和3需要一直等到锁A被释放。然后在它们尝试对B或C加锁之前,必须成功地对A加了锁。

    2)加锁时限 :

    另外一个可以避免死锁的方法是在尝试获取锁的时候加一个超时时间,这也就意味着在尝试获取锁的过程中若超过了这个时限该线程则放弃对该锁请求。

    并会进行回退并释放所有已经获得的锁,然后等待一段随机的时间再重试。这段随机的等待时间让其它线程有机会尝试获取相同的这些锁,

    并且让该应用在没有获得锁的时候可以继续运行(加锁超时后可以先继续运行干点其它事情,再回头来重复之前加锁的逻辑)。

    3)死锁检测:

    每当一个线程获得了锁,会在线程和锁相关的数据结构中(map、graph等等)将其记下。除此之外,每当有线程请求锁,也需要记录在这个数据结构中。

    当一个线程请求锁失败时,这个线程可以遍历锁的关系图看看是否有死锁发生。如果检测到死锁,就释放所有锁,回退,并且等待一段随机的时间后再重试

     

    遇到死锁怎么办

    我们先了解下死锁定理: 
                         ①如果资源分配图中没有环路,则系统没有死锁; 
                         ②如果资源分配图中出现了环路,则系统可能有死锁。

    从上面的死锁定理中我们可以知道只要打破死锁的环路就可以解开死锁,以下是处理死锁的两种名方法:

    1)抢占资源:挂起某些死锁进程,并抢占它的资源,将这些资源分配给其他的死锁进程。但应防止被挂起的进程长时间得不到资源,而处于资源匮乏的状态。

    2)终止(或撤销)进程:终止或撤销系统中的一个或多个死锁进程,直至打破死锁状态

     

     

     

     

     

     

     

     

     

    转载于:https://www.cnblogs.com/zzjlxy-225223/p/11148701.html

    展开全文
  • 我们平时在使用mysql数据库时可能会遇到各种各样的小问题,这是很正常的,比如说mysql更新数据库导致锁表了,该怎么办呢?SHOWPROCESSLIST但是此命令只能显示前100条数据,要想看全部的数据的话,请输入:...

    我们平时在使用mysql数据库时可能会遇到各种各样的小问题,这是很正常的,比如说mysql更新数据库导致锁表了,该怎么办呢?SHOW PROCESSLIST

    但是此命令只能显示前100条数据,要想看全部的数据的话,请输入:SHOW FULL PROCESSLIST

    下面这个命令里面最关键的就是state列了,mysql列出的状态主要是有以下几种的:Checking table

    正在检查数据表。Closing tables

    正在将表中修改的数据会刷新到磁盘中,同时会正在关闭已经用完的表。Connect Out

    复制从服务器正在连接主服务器。Copying to tmp table on disk

    正在创建临时表用来存放部分查询结果。deleting from main table

    服务器正在执行多表删除中的第一部分,刚删除第一个表。deleting from reference tables

    正在执行FLUSH TABLES,等待其他线程关闭数据表。Killed

    被其他查询锁住了。Sending data

    下面正在处理SELECT查询的记录,同时正在把结果发送给客户端。Sorting for group

    正在为GROUP BY做排序。Sorting for order

    正在为ORDER BY做排序。Opening tables

    这个过程应该会很快,除非受到其他因素的干扰。Removing duplicates

    正在执行一个SELECT

    DISTINCT方式的查询,但是MySQL无法在前一个阶段优化掉那些重复的记录。因此,MySQL需要再次去掉重复的记录,然后再把结果发送给客户端。Reopen table

    获得了对一个表的锁,但是必须在表结构修改之后才能获得这个锁。已经释放锁,关闭数据表,正尝试重新打开数据表。Repair by sorting

    修复指令正在排序以创建索引。Repair with keycache

    修复指令正在利用索引缓存一个一个地创建新索引。它会比Repair by sorting慢些。Searching rows for update

    正在讲符合条件的记录找出来以备更新。它必须在UPDATE要修改相关的记录之前就完成了。Sleeping

    正在等待客户端发送新请求.System lock

    正在等待取得一个外部的系统锁。如果当前没有运行多个mysqld服务器同时请求同一个表,那么可以通过增加--skip-external-locking参数来禁止外部系统锁。Upgrading lock

    INSERT DELAYED正在尝试取得一个锁表以插入新记录。Updating

    正在搜索匹配的记录,并且修改它们。User Lock

    正在等待GET_LOCK()。

    Waiting for tables

    该线程得到通知,数据表结构已经被修改了,需要重新打开数据表以取得新的结构。然后,为了能的重新打开数据表,必须等到所有其他线程关闭这个表。以下几种情况下会产生这个通知:FLUSH

    TABLES tbl_name, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE

    TABLE,或OPTIMIZE TABLE。waiting for handler insert

    假如发现锁表进程,请输入kill指令将他剔除KILL "id"

    那么以上就是本篇文章的所有内容了,还想了解更多java常见问答知识吗?如果是的话,赶快来关注本站消息获取吧。

    推荐阅读:

    展开全文
  • 今天面试被问到数据库连接池满了怎么解决?只回答了将maxActive改大,面试官不满意,回来想想应该是想让我答查看是否是锁表造成的,如果是,则 查询Mysql 哪些表正在被锁状态  方法1: show OPEN TABLES where In_...

    今天面试被问到数据库连接池满了怎么解决?只回答了将maxActive改大,面试官不满意,回来想想应该是想让我答查看是否是锁表造成的,如果是,则

    查询Mysql 哪些表正在被锁状态
     方法1: show OPEN TABLES where In_use > 0;
     方法2: **SHOW PROCESSLIST;**查看数据库中表的状态,是否被锁

    解锁锁定的表
     kill id

    展开全文
  • 本文针对我们平时使用场景最多的MySQL数据库在RR隔离级别下容易产生幻读的问题,来进行分析并分享解决方案。PartⅠ 问题回顾幻读的定义:幻读是指某个事务读取某个范围内的记录时,另外一个事务又在该范围内插入新...
  • 之前有遇到过这个问题,解决后没有记录下来,导致今天又忘记怎么解决了,又白白浪费时间,今天就把解决方法记录下来,为了自己也给遇到这个问题的朋友一个参考: 当在操作某张表的时候,如果你当你要对那张表...
  • 使用for update卡住锁表解决办法(转) 今天使用select * from bd_corp for update改好几次之后,突然执行N长时间都不行,马上给用友打电话,我听到锁表”两个字。 马上查询百度。 们在操作数据库的...
  • Oracle 锁表与解锁表

    2018-10-28 10:36:00
    之前在项目中做同步任务的时候,需要从一个接口中拿到数据,插入到数据库中,使用的是Merge Into;... 对表的操作在短时间内非常的频繁会导致数据库锁表;  解决办法 查询被锁的会话ID:  select sessi...
  • 最近开发遇到一个问题,由于数据量比较大,所以执行一条SQL语句可能死住,数据库忙的话,就会将当前的数据库进程住,而就执行这样...好,怎么解决住的数据库进程?如果在WINDOWS下的可以打开PL/SQL,简单的方法就...
  • 原 Oracle 锁表与解锁表 2018-10-28 10:36:00 qq_38593865 阅读数 116 ...最后问老大,老大说是锁表的问题;这才解决;同时也百度别人是怎么写的,在这里整理一下; 对表的操作在短时间内非常的频繁会导致数据库...
  • 如图 2模块和3模块请求同一张表 在它查询慢的时候我查看数据库有发现的情况 等它查询结束 请求出数据的时 在查询被也就没有 前端是6个模块一起请求的 要怎么优化 如果让前端逐一请求 效果是不是太差...
  • oracle 锁表 及 解锁

    2016-01-04 09:12:00
    后来找半天才发现,原来是我删除数据之后没有提交事物造成了数据库锁表,然后又不明白, 什么是锁表呢,于是就上网去查 查半天,大多数都是说怎么解决锁表和查询锁表的,但是只了解方法还不够,又想知道原理...
  • 使用for update锁表解决办法(转)

    万次阅读 2014-10-21 16:08:22
    今天使用select * from bd_corp for update改好几次之后,突然执行N长时间都不行,马上给用友打电话,我听到锁表”两个字。 马上查询百度。 们在操作数据库的时候,有时候会由于操作不当引起数据库...
  • 今天使用select * from bd_corp for update改好几次之后,突然执行N长时间都不行,马上给用友打电话,我听到锁表”两个字。 马上查询百度。 们在操作数据库的时候,有时候会由于操作不当引起数据库表被...
  • 是为了解决并发环境下资源竞争的手段,其中乐观并发控制,悲观并发控制和多版本并发控制是数据库并发控制主要采用的技术手段,而MySQL中的就是其中的悲观并发控制。MySQL中的有很多种类,我们可以按照下面方式...
  • 今天使用select * from bd_corp for update改好几次之后,突然执行N长时间都不行,马上给用友打电话,我听到锁表”两个字。 马上查询百度。 们在操作数据库的时候,有时候会由于操作不当引起数据库表被...
  • 不论是我们平时接触到的synchronized还是ReentrantLock等等,都是为了解决业务中并发的问题,而数据库中也是如此,mysql里面的大致分为三种,全局和行锁三类。今天这篇文章,将会和你分享全局级...
  • 不论是我们接触过的synchronized还是ReentrantLock等,都是为了解决业务中并发的问题,而数据库中也是如此,MySQL里面的大致分为三种,全局和行锁三类。今天这篇文章,将会和你分享全局。 ...
  • 死锁,会出现这样的情况,不释放,无论多久都读取不数据,一直加载中! 原因二: 里面的数据量太大造成的。 原因三: 网络慢,卡,数据不能传输。 经过分析,个人觉得是愿意一导致我的问题,所以,百度下...
  • 解决数据库并发问题

    2008-12-14 23:07:11
    数据库表abc已经写死,不能随意的添加字段. [b]问题补充:[/b] 好象不行哦.constraint a primary key(cat_id,section_id,attr_id) 是复合主键盘,不行的.更新的是key_attr_seq 字段. [b]问题补充:[/b] key_attr_seq...
  • Mysql数据库用Innodb建表后,如果操作不当,可能会引发死锁。...查询是否锁表show OPEN TABLES where In_use > 0;2.查看当前的事务SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;3.查看当前锁...
  • 对于事务与并发以前了解下,也以为自己知道怎么回事。可是最近又被这事务及并发搞得晕乎(最近脑袋很不好使,缺氧啊),事务为了解决什么?多个事务的并发又有什么问题?于是google,做个笔记,以后忘记...
  • 有个问题一直不太明白,假如商品G的数量为1,用户A和B在同一时间点下购买按钮,购买的数据库操作就是商品中商品的数量-1。那么要如何保证A和B中只有一人能购买成功呢。从数据库层面上,有三种解决方式:1.悲观...
  • MySQL 作为主流的数据库,是各大厂面试官百问不厌的知识点,但是需要了解到什么程度呢?仅仅停留在 建库、创、增删查改等基本操作的水平可不够。在面试后端开发的时候,一连几个问题,简直会被问到一脸懵逼。 ...
  • 可以按照锁的粒度把数据库锁分为级锁和行级锁。级锁Mysql中锁定 粒度最大 的一种锁,对当前操作的整张加锁,实现简单 ,资源消耗也比较少,加锁快,不会出现死锁 。其锁定粒度最大,触发锁冲突的概率最高,...
  • MySQL 五

    2021-01-21 16:45:16
    文章目录按照锁的粒度分数据库锁有哪些?锁机制与InnoDB锁算法?从锁的类别上分MySQL都有哪些锁呢...在关系型数据库中,可以按照锁的粒度把数据库锁分为行级锁(INNODB引擎)、级锁(MYISAM引擎)和页级锁(BDB引擎 )。 My
  • 项目中并发下单的问题怎么解决

    千次阅读 2016-10-12 20:43:59
    解决方法肯定是用文件锁了,具体怎么做看数据库区的mysql模块下的mysql。 使用文件,先试试有没有其他方法,具体如下。 背景知识:数据库存储引擎、表锁、文件数据库存储引擎: 如果是mysiam引擎,则...
  • 从网上搜索原因,主要是以下几个原因:原因一:死锁,会出现这样的情况,不释放,无论多久都读取不数据,一直加载中!原因二:里面的数据量太大造成的。 原因三:网络慢,卡,数据不能传输。经过分析,98%是...

空空如也

空空如也

1 2 3 4 5 6
收藏数 118
精华内容 47
关键字:

数据库锁表了怎么解决