2012-08-22 35 views
0

我试图插入一些数据没有重复,可能来自2+并发进程。插入数据没有重复

不幸的是,在这种情况下,由于数据库设计(删除的行用deleted=1标记,这些可以作为重复项存在),我不能使用唯一约束。

看来一个简单的事务将不起作用 - 我能想到的最好的是SELECT ... FOR UPDATE,但这还不够 - 如果没有行存在,没有行将被锁定,因此它不会阻止插入。另一方面,我想避免锁定整个桌子来写作。

有没有一些很好的方法来解决这个问题?表引擎是InnoDB。 (次要的问题是 - 如何使它在SQLAlchemy的工作,但我可以,如果用普通的工作解决翻译)

编辑:你可以假设模式:

deleted tinyint(1) default null, 
id int(11) not null auto_increment, 
address varchar(255) default null, 
... 

其中地址应该是唯一用于deleted == 0的条目。

+0

我们可以看到示例模式,索引,数据吗? – Kermit

+0

@njk更新,我认为应该足够了 – viraptor

+0

你看过'INSERT ... ON DUPLICATE KEY UPDATE'语法吗? http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html – Kermit

回答

0

沿着这一思路:

insert into target 
    select * from source1 
    union 
    (select * from source2 where not (source2.id in (select id from source1))) 

的多个表添加更多union子句。

+0

我的场景是两个进程将'insert into thetable(deleted,address)values(0,'123')',而不是从一个进程中的两个源插入。 – viraptor

0

你可以试试这个插入查询:

INSERT IGNORE INTO tbl(id,deleted,address) 
SELECT CASE WHEN EXISTS (SELECT id FROM tbl 
         WHERE deleted=0 AND address='new_address') 
     THEN id ELSE NULL END, 
     0, 
     'new_address' 
FROM tbl 
LIMIT 1 

如果给定的地址行和删除= 0在表中已经存在,它将尝试插入行具有相同的ID,这显然不会因为id是主键。 但是,如果没有这样的行,它会尝试插入一个NULL作为id行,这将成功。