start transaction; select * from t where id='x'; if not exist: insert into t(id,c) values('x',1); else: update t set c=c+1 where id='x'; commit;
However, there will be a problem. If two concurrent inserts with id='x' arrive at the same time, they will not be found when selecting, and a primary key conflict will occur when inserting. How to make two concurrent inserts operate sequentially and the next insert is updated based on the result of the previous insert? Because in mysql RR mode, transactions are isolated from each other, if transaction 1 has been successfully inserted and committed, in transaction 2, no data is selected for the first time, and the result of the second select is the same (if there is no update). Another problem is if it perceives that another transaction has inserted data. I studied mysql and summarized it:
start transaction; select * from t where id='x'; // get data if exist: update t set c=c+1 where id='x'; //If it exists, it can be updated directly return; rows=insert ignore into t(id,c) values('x',1); // insert ignore, if it does not exist, it will return 1 to indicate successful insertion, if it already exists, it will return 0 if rows==1: return; // Insert a row that does not currently exist, you can return else rows==0: // Indicates that the row with id='x' already exists in the database when inserting update set d='xxx' where id='x'; // Update a column that is not too new, such as time, get the lock, because after the update, select can get the latest row and lock the record select * from t where id='x'; // The latest row is obtained at this time, and other updates are locked nc=c; // The c obtained by the program is the current latest c nc+=1; //Recalculate in the application update t set c=nc where id='x'; // finally update back commit;
Use the mysql command to demonstrate: