I have a rules
table consist of a column called priority
, that must be gapless, incremental and unique.
A user must be able to re-order priority of the rules. For example, if there are 10 rules for a user and she moves the last rule to the 5th place, all of the other records between must get updated.
To prevent race condition during updates, I can use a select ... for update
lock. But I can't find a way to guarantee the uniqueness of priority
during inserts.
Firstly I wanted to use a deferred unique constraint, but figured out that MySql does not support this feature as Postgres do.
Then I thought about using a trigger on before insert, to calculate the priority, but I found that duplications still can show up.
What must I do? Is there any way to create a unique check that only works during inserts not updates?
Preventing Duplicates in MySQL Without Using Unique Constraint
lockingMySQLunique-constraint
Related Question
- Mysql – Unique key constraint in thesql
- Mysql – Lock thesql table to prevent select and insert at the same time
- PostgreSQL – How to Lock Tables for Specific Select Queries
- PostgreSQL 9.6 – Constraint to Prevent Duplicates When Column > 0
- Oracle – Preventing Inserts with Unique Constraint
- SQL Server Locking – Insert with Function Result to Prevent Duplicates
Best Answer
Using
SELECT ... FOR UPDATE
on repeatable read (which is the default isolation level in MySql) may lead to gap locks and poor performance.If the list you're maintaining has limited items (e.g. ~100 rules for each user), I suggest to add a column named
version
and hold a unique constraint/index on <priority, version> and then try to mimic eventual consistency. Here's an example:To bring up the 4th row (with priority = 2) to the 2nd place (which has priority = 4), you should:
This way, all of the rows will eventually have the same version and there will be no duplicate priorities (in that version).