【发布时间】:2012-07-05 09:46:54
【问题描述】:
我一直在开发一个应用程序来处理帐户和通过这些帐户进行的交易。
目前,应用程序使用的表按以下方式建模:
帐户 +----+-----------------+---------+------+ |编号 |当前余额 |版本 | ... | +----+-----------------+---------+------+ | 1 | 1000 | 48902 | ... | | 2 | 2000 | 34933 | ... | | 3 | 100 | 103 | ... | +----+-----------------+---------+------+ account_transaction +--------+-------------+----------+----- --+------------------+--+ |编号 | account_id |日期 |价值 |结果金额 | ... | +--------+-------------+----------+----- --+------------------+--+ | 101 | 1 | 2012 年 5 月 3 日 10:13:33 | 1000 | 2000 | ... | | 102 | 2 | 2012 年 5 月 3 日 10:13:33 | 500 | 1500 | ... | | 103 | 1 | 2012 年 5 月 3 日 10:13:34 | -500 | 1500 | ... | | 104 | 2 | 2012 年 5 月 3 日 10:13:35 | -50 | 1450 | ... | | 105 | 2 | 2012 年 5 月 3 日 10:13:35 | 550 | 2000 | ... | | 106 | 1 | 2012 年 5 月 3 日 10:13:35 | -500 | 1000 | ... | +--------+-------------+----------+----- --+------------------+--+每当应用程序处理一个新事务时,它都会在 account_transaction 中插入一个新行,并且在 account 表中,它会更新列 current_balance 存储帐户的当前余额和用于乐观锁定的列版本。 如果乐观锁定有效,则提交事务,否则回滚事务。
作为一个粗略的例子,在处理事务 102 时,应用程序执行了 以下伪 SQL/JAVA:
设置自动提交 = 0; 插入 account_transaction (account_id、日期、值、结果金额) 价值观 (2, sysdate(), 550, 2000); 更新帐户集 current_balance = 2000, 版本 = 34933 在哪里 id = 2 和 版本 = 34932; if (ROW_COUNT() != 1) { 回滚; } 别的 { 犯罪; }但是,某些帐户非常活跃,并且会同时接收许多事务,这会导致 MySQL 在更新 account 表中的行时出现死锁。这些死锁给应用程序带来了严重的性能损失,因为当数据库发生死锁时,它会导致重新处理事务。
如何有效地处理账户的当前余额?当前余额用于授权/拒绝新交易并用于各种报告。
【问题讨论】:
标签: mysql performance database-design concurrency