如果不存在MySQL插入查询线程安全

时间:2015-09-18 10:52:07

标签: mysql innodb

我在MySQL中有一个表(需要用last_updated_date进行分区)。但是我希望表的col1中的值是唯一的(但是由于MySQL要求分区列包含在每个唯一键约束中,因此我不能仅在col1上创建主键)。现在我有这个查询在表中插入一条记录

INSERT INTO TAB1 (col1, clo2, clo3) SELECT 'val1', 'val2', 'val3'
from dual WHERE NOT EXISTS (SELECT * from TAB1 where col1 = 'val1');

上述查询将确保在非并行插入的情况下col1的唯一性。但是,我想确认它是否也能确保col1在2个连接并行插入时的唯一性,即上述查询线程是否安全?

注意:我使用的是InnoDB engine

2 个答案:

答案 0 :(得分:2)

我认为对于你想做的事情有一个非常好的解决方案。将col1作为第一个分区键,几乎会导致您按last_update_date分区的原因。

一个kludge做范围分区有一些荒谬的宽范围,所以一切都在一个分区。您可以使用range columns执行此操作。

partition by range columns (id, last_updated_date)
    partition p0 values less than (9999999999, '2015-01-01'),
    . . .
);

然后,您可以包含unique约束。缺点是您需要与所有id子句where中的where id < 9999999999进行比较。

另一种方法是使id成为自动递增的ID。在这种情况下,您不必担心重复。

或者,在每个分区中使id唯一,并在您的问题中使用查询。这不是100%肯定,但碰撞的条件是:

  • 2+插入线程正在运行
  • 重复项可能会进入相邻的分区

第二个需要分区切换,这是非常罕见的,因此碰撞的可能性非常低。

答案 1 :(得分:0)

设置:索引以col1开头。 (制作UNIQUE是没用的,因为您必须向其添加last_updated_date。)

BEGIN;
SELECT 1 from TAB1 where col1 = 'val1'  FOR UPDATE;
If you got 1, ROLLBACK and exit.
INSERT INTO TAB1 (col1, clo2, clo3) VALUES ('val1', 'val2', 'val3')
COMMIT;

另一方面说明......使用PARTITION会带来什么好处?