同时插入MySQL(innodb)

时间:2014-07-30 09:11:41

标签: mysql innodb database-concurrency

考虑我们在数据库t_log中有一个表Test。 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和检查,发现两条记录都有效并插入。然后t_log将包含无效的两条记录。

有两种防止这种无效记录的好方法吗?谢谢。

1 个答案:

答案 0 :(得分:0)

使用算术根据需要生成唯一值:

  • 创建一个新列,例如action_hash int
  • (F_trans_id, action_hash)
  • 上创建唯一索引
  • 创建一个触发器,在需要时使用不同的值填充action_hash

在你的例子中,我能想到的最简单的事情是:

new.action_hash = new.F_log_id * (new.F_action - 1)

F_action1时,这将为零,这要求F_trans_id是唯一的,否则不会。