Re: UPSERT with non-unique index
"J.O. Aho" <[email protected]> Sun, 2 Aug 2020 20:15:03 +0200
| Newsgroups | comp.databases.mysql |
|---|---|
| Message-ID | <[email protected]> |
On 02/08/2020 18.55, Stanimir Stamenkov wrote: > [I've posted this on Stack Overflow: > https://stackoverflow.com/questions/63194116/upsert-with-non-unique-index] > > I need to implement concurrent-safe UPSERT using a non-unique key and > avoid unnecessary auto-increment of ID. > > Traditional INSERT ... ON DUPLICATE KEY [1] doesn't work for me, so I'm > performing: > > INSERT INTO table (col1, col2, col3, col4, col5) > SELECT 1, 2, 'value3', 'value4', 'value5' > WHERE NOT EXISTS (SELECT 1 > FROM table > WHERE col3 = 'value3' > AND col4 = 'value4' > AND col5 = 'value5') > > then if it results in no row inserted, I'm performing: > > UPDATE table > SET col1 = col1 + 1, > col2 = MAX(col2, 2) > WHERE col3 = 'value3' > AND col4 = 'value4' > AND col5 = 'value5' > > There's an index: > > CREATE INDEX ON table (col3, col4, col5) > > It is non-unique as there are legacy data that does not allow me to > declare it unique. Newer records, however, should not have duplicated > (col3, col4, col5) rows. > > Unsurprisingly, using the given INSERT statement I'm getting mixed > results trying to execute it concurrently from two sessions. I can see > the second session blocking until the first one commits its transaction, > but then the second transaction is also able to insert a new row > sometimes (or sometimes it achieves the expected of avoiding to insert a > duplicate (col3, col4, col5) row). Maybe the blocking is more then way you are testing things than what in reality happens. I would suggest you use LOCK TABLES table WRITE; <do what you did before> UNLOCK TABLES; LOCK TABLES table WRITE; UNLOCK TABLES; https://www.mysqltutorial.org/mysql-table-locking/ https://dev.mysql.com/doc/refman/5.7/en/lock-tables.html -- //Aho