确保多个Java客户端访问数据库时的数据完整性
我有一个MySql数据库实例,其中帐户表维护余额字段。我有多个Java应用程序,每个使用Jdbc连接到数据库,这可能会增加或减少字段的值。我如何确保读取,计算和更新值,并且此过程是孤立发生的,并且“知道”可能正在执行同一事情的任何其他Java进程?确保多个Java客户端访问数据库时的数据完整性
简单的答案是使用交易: http://dev.mysql.com/doc/refman/5.0/en/commit.html
然而,在你所描述的情况下,我更喜欢不保存的帐户在表中的列的平衡,但通过总结来计算的话与该账户相关的交易的价值。它对你提出的完整性问题不太敏感,而且你不太可能遇到模糊的锁定方案。
在一个已经有1000年交易的长期账户中,你总会总结那些每次都能找到余额的账户吗?或者有什么策略可以避免这种情况,比如维持每年的平衡? –
通常,调整良好的数据库系统并不真正减慢SUM中数百和数十个记录之间的速度。当然,如果你必须计算出数千个账户的余额,那可能不那么容易。在这种情况下,我使用了一种类似于您的建议的策略:有效地归档历史交易,并创建与这些归档交易总和的“期初余额”交易。 –
一个简单的方法是JDBC事务管理。请参阅java.sql.Connection.setAutoCommit()
文档。它使您能够明确禁用自动语句提交:
Connection c = /* retrieve connection */
c.setAutoCommit(false);
c.setTransactionIsolation(/* depends on your requirements */);
c.executeQuery(/* */);
c.executeUpdate(/* */);
c.commit(); /* or c.rollback() */
在真实的场景中,你必须引入一个finally
块提交或rolback交易,否则你可能在你的数据库死锁结束。
编辑:如果您的Java应用程序是最终用户客户端,则用户总是有风险,即用户直接连接到数据库(例如使用Access)绕过您的事务管理逻辑。这是我们开始在两者之间放置应用程序服务器的原因之一。解决方案也可能是实现存储过程,以便客户端根本不与表进行交互。
如果您使用的是InnoDB引擎,那么您可以使用MySQL record level locking锁定来自其他客户端的更新的特定帐户记录。
更新:替代地,您可以应用程序级锁描述为here。
从参考手册 - '死锁可能...'和'一般来说,表锁优于行级锁' - 不会激发信心。您是否使用了行级锁定,并且使用起来很简单?你有没有关于如何使用Jdbc执行“锁定”的示例代码?谢谢。 –
这就是为什么RDBMSs首先被发明出来的原因。 – Ingo