在使用全管系列软件的过程中,偶尔会出现提示“数据更新时发生冲突,请重试。”,如下图:

image.png

出现这种提示框并不是软件出错,而是软件检测到存在数据并发冲突而采取的保障措施,点击【确定】后,再点一次提交按钮即可。

并发冲突原因分析

以上面的案例举例说明,销售出库单过账时,会增加客户的当前应收,当多个用户对同一个客户的多张销售出库单同时进行过账时,就可能导致并发冲突。

比如:

客户A的当前应收为100元;

用户甲执行销售出库单1过账会导致客户A的当前应收增加200元,即:客户A当前应收 = 100 +200 = 300元。

然后用户乙执行销售出库单2过账会导致客户A的当前应收增加500元,即:客户A当前应收 = 300 +500 = 800元。

在无并发冲突的情况下,执行过程就如上面的步骤。当恰好同时(称为并发)过账两张出库单时,就可能影响上面步骤的正常运行,如下所示:

用户甲执行销售出库单1过账会导致客户A的当前应收增加200元,即:客户A当前应收 = 100 +200 = 300元。

用户乙并发执行销售出库单2过账会导致客户A的当前应收增加500元,即:客户A当前应收 = 100 +500 = 600元。

上面用户乙并发执行销售出库单2时出现错误,原因是读取数据和写入数据是两个动作,在并发情况下,用户甲和用户乙的读写动作可能会交替执行,如下图所示:

1.用户甲读取客户A当前应收=100

2.用户乙读取客户A当前应收=100

3.用户甲写入客户A当前应收=100+200=300

4.用户乙写入客户A当前应收=100+500=600

上面的第4步就出现了并发冲突,原因是客户A当前应收已经被用户甲更新为300,而用户乙仍然使用错误的旧数据100来执行数据更新,导致最终结果错误。

并发冲突解决措施

思路一:避免交替执行。将读取和写入放入一个事务,并且规定事务只能顺序执行,即排队执行事务,一个执行后再执行下一个。这种方式可以彻底解决并发冲突,但代价是性能很差,白白浪费了硬件资源。

上面思路一的性能太差,所以为了保证系统性能,只能考虑采取措施来检测并发冲突,当出现并发冲突时阻止写入错误的数据,全管平台采用的就是这种思路:

当系统检测到并发冲突时,系统阻止写入错误的数据,并弹出提示框。如果是点击过账按钮时弹出并发冲突提示,确定后再点一次过账按钮即可。如果是保存数据时弹出并发冲突提示,确定后再点一次提交按钮即可。

性能建议

提高硬件性能可以减少并发冲突,如果每个读写动作都执行很快,出现冲突的可能性也会减少。

提高数据库性能可以减少并发冲突,主要手段是增加索引。以出库单偏移库存为例,出库单过账时,会按物料+仓库查找出库存数据,再执行该库存的数量增减。如果对库存表建立了“物料+仓库”的索引,查找速度就快,出现并发冲突的可能性也会减少。

另外,不当的设计可能导致并发冲突增加,特别是使用异步执行要谨慎,比如异步执行一批单据的过账,就会导致并发执行一批单据的过账动作,必然增加并发冲突的可能性。