在高负载期间 mysql 中创建了多条记录
Multiple records getting created in mysql during high load
我正在 spring 数据 jpa 应用程序中工作。正如我们所知,通过应用 spring @Transactional 注释,它遵守 ACID 属性。但是我有一个问题。以下是我的解释。
在我当前的应用程序中,给定 post 的业务规则允许用户只回答一个答案,如果他想修改他的答案,他可以编辑一个答案但不能创建另一个答案同样post。因此,对于创建和修改答案,我有两种方法。 1.保存方法和2.编辑方法
我的问题是 w.r.t 保存一个有时在生产中无法按预期工作的答案,即它不满足业务规则并且它为同一 [=30] 的同一用户创建了两个答案=].但是在本地环境中,这个问题永远不会发生。编辑方法对本地环境和生产环境都适用。
以下是我的业务逻辑中save方法的示例代码片段。
@Transactional
public void save(Answer answer) {
Integer postId = answer.getQuestionId();
Answer answerFromDb = answerRepository.findByPostIdAndCreatedByIdAndIsDeleted(postId, answer.getCreatedById(), false);
if(null != answerFromDb) {
throw new InvalidException("You have already answer for the current post");
}
answerRepository.save(answer);
}
我们使用的是 mysql 5.6,本地和生产环境的默认隔离级别都是可重复读取。即
mysql> SHOW VARIABLES LIKE 'tx_isolation';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)
注意:所有主键都是自动递增的,生产中有一个 mysql 服务器实例,目前还不是集群。
非常感谢对上述问题有所了解。
重复table阅读:
T1 事务从 table 个答案和 returns 一定数量的行中读取数据。 T1 中的每个后续读取都将具有相同的行。如果另一个并发事务(T2)在 T1 启动后在 table Answers 上插入一行,它(T1)将不知道有一个新行。
因此,一种可能的解决方案是在 Answers table 上添加一个唯一键,使其匹配 findByPostIdAndCreatedByIdAndIsDeleted
where 条件。
ALTER TABLE `Answers` ADD UNIQUE `unique_index`(`post_id`, `createdBy_id`, `deleted`);
并用 try 包裹保存:
try {
answerRepository.save(answer);
} catch (DataIntegrityViolationException e) {
// ignore (there is already an answer)
}
我正在 spring 数据 jpa 应用程序中工作。正如我们所知,通过应用 spring @Transactional 注释,它遵守 ACID 属性。但是我有一个问题。以下是我的解释。
在我当前的应用程序中,给定 post 的业务规则允许用户只回答一个答案,如果他想修改他的答案,他可以编辑一个答案但不能创建另一个答案同样post。因此,对于创建和修改答案,我有两种方法。 1.保存方法和2.编辑方法
我的问题是 w.r.t 保存一个有时在生产中无法按预期工作的答案,即它不满足业务规则并且它为同一 [=30] 的同一用户创建了两个答案=].但是在本地环境中,这个问题永远不会发生。编辑方法对本地环境和生产环境都适用。
以下是我的业务逻辑中save方法的示例代码片段。
@Transactional
public void save(Answer answer) {
Integer postId = answer.getQuestionId();
Answer answerFromDb = answerRepository.findByPostIdAndCreatedByIdAndIsDeleted(postId, answer.getCreatedById(), false);
if(null != answerFromDb) {
throw new InvalidException("You have already answer for the current post");
}
answerRepository.save(answer);
}
我们使用的是 mysql 5.6,本地和生产环境的默认隔离级别都是可重复读取。即
mysql> SHOW VARIABLES LIKE 'tx_isolation';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)
注意:所有主键都是自动递增的,生产中有一个 mysql 服务器实例,目前还不是集群。
非常感谢对上述问题有所了解。
重复table阅读:
T1 事务从 table 个答案和 returns 一定数量的行中读取数据。 T1 中的每个后续读取都将具有相同的行。如果另一个并发事务(T2)在 T1 启动后在 table Answers 上插入一行,它(T1)将不知道有一个新行。
因此,一种可能的解决方案是在 Answers table 上添加一个唯一键,使其匹配 findByPostIdAndCreatedByIdAndIsDeleted
where 条件。
ALTER TABLE `Answers` ADD UNIQUE `unique_index`(`post_id`, `createdBy_id`, `deleted`);
并用 try 包裹保存:
try {
answerRepository.save(answer);
} catch (DataIntegrityViolationException e) {
// ignore (there is already an answer)
}