假设我们在数据库 Test
中有一个表 t_log
。 t_log 如下所示
create table `t_log`(
`F_log_id` bigint(20) not null AUTO_INCREMENT,
`F_trans_id` bigint(20) not null,
`F_action` tinyint(3) not null,
primariy key(`F_log_id`)
)engine=innodb
假设F_action
字段只能取几个特定值,如1和2。对于F_action
=1条记录,对应的F_trans_id
必须不同于彼此。而对于 F_action
=2 条记录,对应的 F_trans_id
可以采用相同的值。
例如表中类似以下的记录应该是有效的
F_log_id | F_action | F_trans_id
1 1 1001
2 2 1002
3 2 1002
但是像下面这样的记录应该无效
F_log_id | F_action | F_trans_id
1 1 1001
2 1 1001
3 2 1002
由于我们对F_trans_id
的唯一限制取决于F_action
的具体值,因此我们不能仅仅在F_trans_id和F_action上建立唯一索引。
为了保持一致性,将记录插入到 t_log 中被放入这样的事务中
start_transaction()
select and check if valid
do inserting
commit()
但是在高并发环境下,可能有两个插入事务几乎同时到达,比如都进入了start_transaction(),假设两条记录都是(F_action=1, F_trans_id=222),当select and检查,发现两条记录都有效并插入它。那么t_log
将会有两条无效记录。
有什么好的方法可以防止这种无效记录吗?谢谢。
最佳答案
根据需要使用算术生成唯一值:
- 创建一个新列,例如
action_hash int
- 在
(F_trans_id, action_hash)
上创建唯一索引 - 创建一个触发器,在需要时使用不同的值填充
action_hash
在您的示例中,我能想到的最简单的事情是:
new.action_hash = new.F_log_id * (new.F_action - 1)
当F_action
为1
时,该值为零,这要求F_trans_id是唯一的,但其他情况下则不然。
关于mysql - MySQL(innodb)中同时插入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25032888/