描述:新创建一个玩家账号时,GM给金币或者完成每日任务。调系统时间使得服务器超时,重新登录后发现玩家数据未被正常记录。
排查
(1)反序列化部分,重新登陆后反序列化数据就不正确。
(2)序列化部分,序列化内存数据正确
(3)查看mysql数据日志,写入失败
分析
(1)mysql写入步骤:mysql写入分俩个步骤,save和update. 数据对象被创建时,使用save; 之后数据变化将脏数据写入时,使用update. 同时还有个version参数,用来验证版本是否可写入,写入则自加操作。
(2)查看失败原因:可视化mysql数据,版本号与最终写入的不一致。日志表现上,存在数据对象的mysql update语句在save之前操作,导致数据库中还没有这个对象,则写入失败,后续的逻辑中,版本号增加后与数据库中的版本不一致,后续一致无法正常写入,则玩家数据异常。
定位问题原因:由于数据库中没有将对象创建出来,而出现了update操作。
难点
如果先创建对象,可能是个空的数据对象,后续如果业务逻辑中某些数据列初始化后没被写进去可能出现反序列化问题。设计希望能在数据库中创建一个完整的对象而仅仅一个对象。如果将这一步挪到各个业务模块中,将会出现大量同样功能的函数写俩遍。
方案
其实我们需要的是知道状态,是否需要立即update的状态。
(1)加参数。告知相关的func
(2)依赖各自模块的func 进行update数据,需要自行保证不会出现在数据库中没有对象的情况下update
(3)区分对象创建和反序列化俩种状态,依据该状态决定是否需要立即update.
方案(1)(2)将难点交给了业务层,强迫思考这个点,但是工作量大.
选择方案(3)
总结:本质问题是对象创建与初始化需要分步骤进行,但由于各业务层繁多,很难完全实现,导致数据库中对象的创建与更新时序错乱而使得数据失效。
修改系统时间导致mysql数据写入失败
于 2022-10-20 19:36:12 首次发布