names
是一个将每个唯一名称映射到id:
CREATE TABLE names (
name VARCHAR(20) NOT NULL,
name_id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (name),
UNIQUE (name_id)
) ENGINE=InnoDB
如果' foobar'已经存储在names
中,我希望得到name_id
。否则我想存储它并获取为其生成的name_id
。
如何做到这一点,处理两个线程竞相添加' foobar的可能性? (注意:我们永远不会从此表中删除。)
我用myISAM写道:
GET_LOCK('foobar');
SELECT name_id FROM names WHERE name = 'foobar';
if name wasn't found
INSERT INTO names SET name='foobar';
SELECT LAST_INSERT_ID(); -- that is, name_id
RELEASE_LOCK('foobar');
但是,我很不清楚如何使用innoDB中的事务和行级锁定来实现这一点。
UPDATE: mySQL要求AUTO_INCREMENT仅用于PK。我使用的是MariaDB,它只需要将AUTO_INCREMENT列定义为键。相应地更新示例。
答案 0 :(得分:1)
尝试以下方法:
INSERT IGNORE INTO names (name) VALUES ('foobar');
IF ROW_COUNT() == 1
THEN SELECT LAST_INSERT_ID() AS name_id;
ELSE SELECT name_id FROM names WHERE name = 'foobar';
END IF;
如果启用了自动提交,则不需要显式事务,INSERT IGNORE
查询周围会有一个隐式事务,使其成为原子事务。
ROW_COUNT()
将告诉您是否能够插入新行;如果名称可用,则为1
,如果找到重复,则为0
,因此无法插入行。