首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在不同的机器上同时处理两个事务

在不同的机器上同时处理两个事务
EN

Stack Overflow用户
提问于 2012-09-20 12:45:57
回答 2查看 782关注 0票数 2

在我的办公室里,我有一个远程网络服务器上的订购平台和一个本地生产机器。两个the服务器都访问同一个远程MySQL (InnoDB)数据库。

我的问题是:生产需要几分钟,其中2-3个交易是开放的。在这段时间里,我生成新的发票号码并增加它们。最近的发票编号保存在数据库中的数字-表中。

代码语言:javascript
复制
public Long getNewInvoiceNumber() {
    Criteria crit = getSession().createCriteria(Numbers.class);
    Numbers n = ((Numbers)crit.uniqueResult());
    Long newNumber = n.getInvoiceNumber() + 1L;
    n.setInvoiceNumber(newNumber);
    return newNumber;
}

现在,当某人在生产过程中保存一个新订单时,他们访问的是相同的数字--表以生成另一个号码(而不是发票)。生产过程中处理的所有订单都以正确的发票编号保存。然而,数字-表没有更新最新的价值和发票号码保持不变的生产前。

据我所知,其中一个事务得到了一条“陈旧表”消息。但是MySQL / Hibernate / Java的行为是什么呢?我想从其中一个事务中获得一个异常,这样我就可以回滚,并且不会有这种危险的数据库不一致。

编辑: --这是表Numbers的样子:

代码语言:javascript
复制
id | invoice_number | tag_number
0  | 16533          | 1055

id是主键。我只访问这一行并增加所需的编号。

编辑2 :好的,我看到这个表结构有点糟糕。我将其更新如下:

代码语言:javascript
复制
id             | number
invoice_number | 16533
tag_number     | 1055

现在我可以独立地访问每一行了。但不知道这是否解决了我的问题。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-09-20 13:19:34

代码语言:javascript
复制
public Long getNewInvoiceNumber() {
    Criteria crit = getSession().createCriteria(Numbers.class);
    crit.setLockMode(LockMode.PESSIMISTIC_WRITE);   // LINE ADDED
    Numbers n = ((Numbers)crit.uniqueResult());
    Long newNumber = n.getInvoiceNumber() + 1L;
    n.setInvoiceNumber(newNumber);
    getSession().update(n);              // LINE ADDED
    return newNumber;
}

如果使用InnoDB,则必须使用MySQL,您应该确保Hibernate在为crit.uniqueResult()部件生成的SQL中添加"FOR UPDATE“。我还会在(停止执行)之后设置一个Java断点,并手动测试相同的SQL查询会导致另一个客户机阻塞。

这将更好地测试您的SQL服务器是否正常,您的方言设置是否正确,基本上该特性适合您。

这将强制在生成下一个InvoiceNumber时在server上进行序列化。

这样,即使1000个用户同时尝试开发票,也永远不会得到相同的2 InvoiceNumber。

注意: LockOptions取代了LockMode来指定关于并发的这一方面的模式内容。有关帮助,请参阅hibernate发布说明。

注:你谈到的交易持续几分钟。当事务未提交时,其他任何用户都无法生成新的发票号。也许您需要将其作为一个嵌套和独立的事务运行。如果由于其他处理错误而未能使用该数字,则InvoiceNumber中会出现问题漏洞。会计/会计系统不喜欢发票编号上的漏洞,也不喜欢过时的顺序。

相关MySQL文档链接https://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html

票数 0
EN

Stack Overflow用户

发布于 2012-09-20 13:19:08

并发处理数据库的方法有多种,例如使用乐观锁或悲观锁(应该小心后者,因为它可能导致延迟和死锁)。

但我想,在您的情况下,您必须在某些事务开始后立即更改Number表,而不是在事务结束时更改。这将确保保留发票的时隙。

查看Hibernate的Id生成器也是有意义的,您可以看到如何实现价值生成机制的不同想法。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12512911

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档