Reputation: 23
ID|RID|SID|Name
1| 1 | 1 |Alpha
2| 1 | 2 |Beta
3| 2 | 1 |Charlie
ID is auto-incrementing unique, not the problem here. RID is grouping sets of data together, I need a way to make the SID unique per RID 'group'. This structure is correct, I anticipate someone saying 'split it into multiple tables', that's not an option here (it's taxonomic classification).
As shown, under RID 1, the SID increments from 1 to 2, but when the RID changes to 2, the SID is 1.
I have the code to get the next value: SELECT IFNULL(MAX(SID),0)+1 AS NextVal FROM t WHERE RID=1
, the question is how do I use that value when inserting a new record?
I can't simply run two queries as that can result in duplication, so somehow the table needs to be locked, ideally to write only. What would be the correct way to do this?
Upvotes: 2
Views: 149
Reputation: 6654
At first you should constraint your data to be exactly the way you want it to be, so put an unique combined index on (RID, SID)
.
For your problem you should start a transaction (BEGIN
) and then put an exclusive lock onto the rows you need, which blocks all access to these rows for other connections (not the whole table, which is poor for performance!):
SELECT .... FOR UPDATE
This locks all selected rows exclusively. Further you should not use READ UNCOMMITTED
as isolation level. you can view in the manual how to check the current isolation level and how to change this.
REPEATABLE READ
is the default isolation level, which would be fine here.
Then insert your new query and commit (COMMIT
) the transaction.
This should prohibit duplicates altogether since you created an unique index and it should also prohibit your scripts just failing with an error message that the unique check failed, but instead wait for other scripts to finish and insert the next row then.
Upvotes: 1