There is no usage of transactions that ensures uniqueness.
Use a UNIQUE
constraint for that.
But you can't make any index, including a unique index, that is over 768 bytes. Which means you can't put a unique constraint on a long string data type like TEXT
, VARCHAR
over a certain length, etc.
You can use a prefix index to make a leading portion of a long string unique.
ALTER TABLE MyTable ADD UNIQUE KEY (textfield(255));
Another method of ensuring uniqueness is to search the existing rows for the value you want to insert, and only if it is not found, insert the new value.
But this requires that you have exclusive access to the table, to prevent a race condition with another concurrent session trying to insert the same value.
This also has nothing to do with transaction isolation level. Even the SERIALIZABLE
isolation level won't help you avoid the race condition. Read http://dev.mysql.com/doc/refman/5.7/en/innodb-transaction-isolation-levels.html which says:
[SERIALIZABLE] is like REPEATABLE READ
, but InnoDB implicitly converts all plain SELECT
statements to SELECT ... LOCK IN SHARE MODE
if autocommit is disabled.
So if multiple sessions concurrently try to read the table to check for a duplicate value, they are allowed to, because shared locks don't block other shared locks. Then they may all decide it's safe to insert the new value, and you have duplicates.
To get an exclusive lock on reading the table, you'd use SELECT ... FOR UPDATE
explicitly. But you can do this in any transaction isolation level.