最近在开发中遇到一个小问题,因为业务设计的问题,数据库表一直锁着,而且不定期加锁,导致服务器运行异常。最后,经过排查原因是多个线程同时更新同一张表中的同一条记录,导致出现问题。今天我将告诉你如何避免这个问题。问题描述最近由于公司业务需要,产品设计了一个业务系统。据说很多内外人员都会用到。系统显示我们的研发部门正在加班赶时间。时隔两个月,系统终于上线运行。.刚开始用的人很少,也没什么问题。感觉系统还是很稳定的。随着后面用的人越来越多,系统开始出现一些莫名其妙的问题。更新了部分业务信息。总是报告错误。查看日志发现表记录被锁定,更新失败。找到错误问题后,我们开始一遍又一遍地翻看日志,各种分析,找出是什么原因导致表记录被锁住。最后发现在这张表的state字段中,同时更新了多个接口方法,并且经常同时操作。即数据库中有多个会话同时操作同一张表中的同一行记录,导致表记录被锁定。问题分析那么定位问题,如何解决呢?这里先了解两个名词:悲观锁(PessimisticLock):简单的解释就是非常悲观。每次去拿数据的时候,都以为别人会修改,所以每次修改数据的时候,都会加锁,让别人想修改。这个数据会一直等到它能拿到锁。乐观锁(OptimisticLock):这个刚好相反,很乐观。每次修改数据,你认为别人不会修改,所以不会被锁,但是你提交更新的时候,你会判断别人是否要更新这条数据。乐观锁适用于读多写少的应用场景,可以提高吞吐量。通过这两种方法可以解决问题,但是选择哪种比较好,我们简单分析一下:悲观锁是通过“select...forupdate”实现的,即在更新表之前锁定这条记录,然后接下来执行更新语句。不过,这个方法有点太重了。毕竟,锁定还是需要大量的时间和成本。不符合业务需求,直接pass。乐观锁比较轻量级,主要实现是在表中增加一个记录版本字段,比如version。那么每次需要更新查询记录时,version=?必须在where后面加上,这样当你从查询中得到版本时,如果其他session更新了这个字段,版本就会和你现在的不一样。这样会让你的更新失效,需要重新获取最新版本,重新执行更新语句。问题已经解决了。经过上面的分析,我们有了比较清晰的解决方案,剩下的就是代码:/***乐观锁更新*@paramid*@return*/publicbooleanupdate(intid){intcnt=0;while(cnt==0){USERuser=query("SELECT*FROMtable_userWHEREid=#{id}",id);cnt=update("UPDATEtable_userSETversion=version+1,status=2WHEREid=#{id}ANDversion=#{version}",id,user.version());if(cnt>0){//返回更新成功returntrue;}}返回假;}这里总结一下就是根据Mysql自身的特点解决这个问题。当然,还有很多其他的方法可以解决。以上就是本次分享的全部内容。想了解更多python知识,请前往公众号:Python编程学习圈,每日干货分享
