我的应用程序中有一些逻辑,我认为这些逻辑会导致以下 MySQL 调用,但是当我在几毫秒内运行其中两个时,我会得到两个不兼容的子行。
- 使用可重复读隔离启动事务。
- 获取并锁定 Account 对象
SELECT ... FROM Account WHERE id = ? FOR UPDATE
- 读取链接到帐户的现有收件人
SELECT ... FROM Address WHERE account_id = ?
- 如果现有地址被标记为主要地址,请更新它。
UPDATE Addresses SET primary = false WHERE id = ?
- 插入primary = true 的新地址。
- 完成交易。
如果这个过程快速运行两次,我会得到两个地址行,其中primary = true,并且account_id设置为帐户,这让我感到惊讶,因为我认为在步骤2中锁定帐户会阻止多个事务同时运行。我不想以过多限制我的吞吐量的方式改变行为。
我想知道是否需要将隔离级别切换为“可序列化”[原文如此],但我不清楚第 3 步中的“FOR SHARE”读取是否能真正解决问题。
我的数据结构从上面可能很明显,但看起来像这样:
Account
:
id
PK
其他不相关的账户数据
Address
:
id
PK,
account_id
- 不是实际的外键,只是与帐户 PK 匹配的 id。
primary
- 布尔值,每个帐户最多应有一个主地址,但这在 MySQL 中并不强制执行,因为使用生成的列来启用此功能会使数据库变得有点复杂,因为 MySQL 不支持部分索引。
其他不相关的地址数据