以下是我希望在Web应用程序中执行的两个潜在工作流程。
变异1
变化2:
在每种情况下,我都想知道:确保对此服务的并发访问能够产生合理结果的标准方法是什么? (即,没有人的编辑被破坏,值对应于编辑的某些顺序等)。
这种情况是假设的,但这里有一些细节,说明我在实践中可能需要处理的问题:
我觉得我宁愿不尝试在这里重新发明轮子。当然,这些是众所周知的解决方案中众所周知的问题。请指教。
感谢。
答案 0 :(得分:6)
据我所知,这个问题没有一般解决方案。
问题的根源在于用户可能会在进行更新和保存之前检索数据并在屏幕上长时间盯着它。
我知道三种基本方法:
当用户读取数据库时,请锁定记录,并且在用户保存任何更新之前不要释放。在实践中,这是非常不切实际的。如果用户打开屏幕,然后在不保存的情况下去吃午餐怎么办?或者回家过一天?或者是如此沮丧地试图更新这个愚蠢的记录,他退出并且永远不会回来?
将您的更新表达为增量而非目的地。举一个典型的例子,假设您有一个记录库存中库存的系统。每次进行销售时,您必须从库存盘点中减去1(或更多)。
所以说现有的数量是10.用户A创造销售。当前数量= 10.用户B创建销售。他还获得当前数量= 10.用户A输入两个单位出售。新数量= 10 - 2 = 8.保存。用户B输入一个售出的单位。新数量= 10(他加载的值) - 1 = 9.保存。显然,出了点问题。
解决方案:写入“更新库存集数量=数量-1,其中itemid = 12345”,而不是写“更新库存集数量= 9,其中itemid = 12345”。然后让数据库对更新进行排队。这与策略#1非常不同,因为数据库只需要锁定记录足够长的时间来读取它,进行更新并写入它。当有人盯着屏幕时,它不必等待。
当然,这仅适用于可以表示为delta的更改。如果你是,比如说,更新客户的电话号码,那就不行了。 (比如,旧数字是555-1234。用户A表示将其更改为555-1235。这是+1的变化。用户B表示将其更改为555-1243。这是+9的变化。所以总变化是+10,客户的新号码是555-1244。:-))但在这种情况下,“最后一位用户点击输入键获胜”可能是你能做的最好的。
[注意:论坛会自动重新编号我的编号列表。我不知道如何覆盖它。]
答案 1 :(得分:0)
应用层中的事情很简单 - 每个请求都由不同的线程(或进程)提供服务,所以除非你的处理类(服务)中有状态,否则一切都是安全的。
当你到达数据库时,事情变得更加复杂 - 即状态被保持。在那里你需要transactions以确保一切正常。
事务具有一组属性 - ACID,“保证可靠地处理数据库事务”。
答案 2 :(得分:0)
如果mysql中没有事务,可以使用update命令确保数据没有损坏。
UPDATE tableA SET status=2 WHERE status = 1
如果status为1,那么只有一个进程可以获得记录更新的结果。在下面的代码中,如果未执行更新,则返回-1(如果没有要更新的行)。
PreparedStatement query;
query = connection.prepareStatement(s);
int rows = -1;
try
{
rows = query.executeUpdate();
query.close();
}
catch (Exception e)
{
e.printStackTrace();
}
return rows;