0

考虑我们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和check的时候,都是找到的记录是有效的并插入它。然后t_log会有无效的两条记录。

有什么好的方法可以防止这种无效记录吗?谢谢你。

4

1 回答 1

0

Use arithmetic to generate unique values as required:

  • create a new column, say action_hash int
  • create a unique index on (F_trans_id, action_hash)
  • create a trigger that populates action_hash with distinct values when needed

In your example, the simplest thing I can think of is:

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

Which will be zero when F_action is 1, this requiring F_trans_id to be unique, but otherwise not.

于 2014-07-30T09:45:30.553 回答