Re: UPSERT with non-unique index

"J.O. Aho" <[email protected]> Mon, 3 Aug 2020 21:55:10 +0200
Newsgroups comp.databases.mysql
Message-ID <[email protected]>
On 03/08/2020 19.45, Stanimir Stamenkov wrote:
> Sun, 2 Aug 2020 20:15:03 +0200, /J.O. Aho/:
> 
>> 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
> 
> Wouldn't this basically block concurrent inserts/updates?  I don't want 
> to block all on the same table trying to insert/update different sets of 
> data.
> 

Yes, it will, the good thing (or sometimes bad) is that the others will 
be waiting for the lock to be released and then do their task.

Unless you do a lot in the transaction, the time the table is locked 
tends to be a lot. If the case is that you do a lot, then I would 
recommend you to break out things, so that the only thing you will do is 
the check for existing values and based on that do the update or insert.
It could be good to make an insert SP that takes care of everything 
(begin transaction (if innodb),locking table, check if key already 
exists and do update else insert, unlock table, commit transaction (if 
innodb)).
See https://dev.mysql.com/doc/refman/5.7/en/create-procedure.html

Without the begin transaction/commit transaction, there is a risk for 
deadlocks, which means that the table never gets unlocked (could happen 
if the locking thread unexpectedly dies) and everyone else who wait for 
access the table will keep on waiting forever.

Other alternative is to move the old data that can have more than one 
row with the same key to a history table and in the current table you 
make the key to a primary key. This will complicate things when you need 
to fetch data, you could of course be able to make a view that selects 
with a union from both tables, this will make it easier when you want to 
join things, but keep in mind it may slow things down.
Alternative you have a switch telling you if you need current data or 
historical data, if you need the historical data, then use the history 
table otherwise the current table.
As I don't know the needs, I can't give you a best option, but some 
options you can look at and then decide yourself which works for you.


-- 

  //Aho