【发布时间】:2012-09-12 20:04:14
【问题描述】:
我在远程网络服务器上有一个订购平台,在我的办公室有一台本地生产机器。 两个网络服务器都访问同一个远程 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 以生成另一个编号(而不是发票)。 生产处理的所有订单都保存有正确的发票编号。 但是,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 个用户同时更改行的行为。
-
两个独立用户可以同时查看来自两个不同事务的相同或旧数据。为了在相对较少的情况下停止这种情况 SELECT ... FOR UPDATE 存在。我会更多地研究这个主题并使用命令行 SQL 客户端测试该理论。
标签: mysql hibernate transactions