names
is a table that maps every unique name to an id:
CREATE TABLE names (
name VARCHAR(20) NOT NULL,
name_id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (name),
UNIQUE (name_id)
) ENGINE=InnoDB
If 'foobar' is already stored in names
, I want to get its name_id
. Otherwise I want to store it and get the name_id
that was generated for it.
How does one do this, dealing with the possibility of two threads racing to add 'foobar'? (Note: we never delete from this table.)
With myISAM I wrote:
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');
However, I'm very unclear about how to achieve this using transactions and row-level locking in innoDB.
UPDATE: mySQL requires that AUTO_INCREMENT only be used for the PK. I'm using MariaDB, which only requires that the AUTO_INCREMENT column be defined as key. Updating example accordingly.