我在远程Web服务器和本地生产机器上有一个订购平台,位于我的办公室。 两个Web服务器都访问相同的远程MySQL(InnoDB)数据库。在不同的机器上休眠两次同时事务
我的问题:生产需要几分钟时间才能打开2-3个交易。在这段时间里,我生成新的发票号码并增加它们。最近的发票号码保存在数据库的Numbers-Table中。现在
public Long getNewInvoiceNumber() {
Criteria crit = getSession().createCriteria(Numbers.class);
Numbers n = ((Numbers)crit.uniqueResult());
Long newNumber = n.getInvoiceNumber() + 1L;
n.setInvoiceNumber(newNumber);
return newNumber;
}
当有人在生产过程中节约了新的订单,他们访问的是同一编号,表生成另一个号码(而不是发票)。 生产处理的所有订单都保存在正确的发票号码中。 但是,Numbers-Table不会更新为最新值,并且发票号码与生产之前保持一致。
我知道其中一个事务会收到“陈旧表”消息。 但是MySQL/Hibernate/Java的行为是什么?我想从其中一个事务中获得异常,这样我可以回滚并且不会有这种危险的数据库不一致。
编辑: 这是表Numbers
的样子:
id | invoice_number | tag_number
0 | 16533 | 1055
id
是主键。我只访问这一行并增加所需的数量。
编辑2: 奥基,我看到这个表结构有点不好。 我把它更新为:
id | number
invoice_number | 16533
tag_number | 1055
现在我可以独立访问的每一行。不知道是否可以解决我的问题。
贵Numbers.class表只能有1排过的?查看setLockMode()/ setLockOptions()的API。您需要SELECT ... FOR UPDATE以确保没有其他用户正在做同样的事情。你也需要getSession()。update(n);对 ? –
是的,截至目前只有1行。我以为数据库有自己的自动锁定模式,我想知道如果有2个用户同时更改行的行为。 – rotsch
两个独立用户可以从两个不同的事务同时查看相同或旧数据。要在相对较少的情况下停止SELECT ... FOR UPDATE存在。我会更多地研究这个话题,并用命令行SQL客户端测试理论。 –