【问题标题】:Ensuring data integrity when database is accessed by multiple java clients确保多个 java 客户端访问数据库时的数据完整性
【发布时间】:2011-11-21 17:38:29
【问题描述】:

我有一个带有 Account 表的 MySql 数据库实例,该表维护一个 Balance 字段。我有多个 Java 应用程序,每个应用程序都使用 Jdbc 连接到数据库,这可能会增加或减少 Balance 字段的值。如何确保读取、计算和更新 Balance 值,并且该过程是独立发生的,并且“了解”可能正在执行相同操作的任何其他 Java 进程?

【问题讨论】:

  • 这就是最初发明 RDBMS 的原因。

标签: java mysql database jdbc data-integrity


【解决方案1】:

一种简单的方法是 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 块来提交或回滚事务,否则您最终可能会在数据库中出现死锁。

编辑:如果您的 Java 应用程序是最终用户客户端,那么您始终面临用户绕过事务管理逻辑直接连接到数据库(例如使用 Access)的风险。这就是我们开始在两者之间放置应用服务器的原因之一。一个解决方案也可能是实现一个存储过程,以便客户端根本不与表交互。

【讨论】:

    【解决方案2】:

    简单的答案是使用事务: http://dev.mysql.com/doc/refman/5.0/en/commit.html

    但是,在您描述的情况下,我更喜欢不将帐户余额存储为表格中的列,而是通过对与该帐户相关的交易的价值求和来计算它。它对您提出的完整性问题的敏感性要低得多,并且您不太可能遇到晦涩的锁定场景。

    【讨论】:

    • 在一个已经有 1000 笔交易的长期账户中,您是否总是每次都将这些相加以找到余额?或者是否有某种策略来避免这种情况,比如保持每年的余额?
    • 一般来说,经过良好调整的数据库系统在 SUM 中的数百到(数万)条记录之间不会真正显着减慢速度。当然,如果您必须计算出数千个账户的余额,那可能并不那么容易。在这种情况下,我使用了类似于您建议的策略:有效地存档历史交易,并使用这些存档交易的总和创建“期初余额”交易。
    【解决方案3】:

    如果您使用的是 InnoDB 引擎,那么您可以使用 MySQL record level locking 锁定特定帐户记录,以便其他客户端的更新。

    更新:或者,您可以使用here 描述的应用程序级锁。

    【讨论】:

    • 来自参考手册 - “死锁是可能的......”和“通常,表锁优于行级锁” - 不会激发信心。您是否使用过行级锁定,是否易于有效使用?您是否有任何示例代码说明如何使用 Jdbc 执行“锁定”?谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-05
    • 1970-01-01
    • 1970-01-01
    • 2010-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多