当前位置:网站首页>Two kinds of updates lost and Solutions

Two kinds of updates lost and Solutions

2022-07-07 21:59:00 fastjson_

Let's first create a user surface ,id Primary key

CREATE TABLE `user` (
  `id` int NOT NULL AUTO_INCREMENT,
  `money` int DEFAULT NULL,
  `version` int DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;


The first type of lost updates ( Rollback lost ) 

 A When the transaction is cancelled , Put what has been submitted B The updated data of the transaction covers . This kind of mistake can cause serious problems , It can be seen from the following account :

Time

Withdrawals A

Transfer transaction B

T1

begin; 
Start business

 

T2

begin; 
Start business

T3

select money from user where id = 1; 
Query account balance as 1000 element     

T4

select money from user where id = 1;
Query account balance as 1000 element

T5

money = 1000 + 100;
update user set money=1100 where id = 1;
Remittance 100 Change the balance to 1100 element

T6

commit;
Commit transaction

T7

money = 1000 - 100;
update user set money=900 where id = 1;
Take out 100 Change the balance to 900 element

T8

rollback;
Roll back the transaction

T9

Balance restored to 1000  element ( Lost update )

A When the transaction is rolled back ,“ Incaution ” take B The transaction has been erased from the account .

stay MySQL database , Any isolation level does not allow the first type of update to be lost


The second kind of lost updates ( Cover lost / Two update questions ) 

A Transaction coverage B Data that the transaction has committed , cause B The operation of the firm is lost : 

Time

Transfer transaction A

Withdrawals B

T1

begin; 
Start business

begin;
Start business

T2

select money from user where id = 1;
Query account balance as 1000 element                 

T3

select money from user where id = 1;
Query account balance as 1000 element

  

T4

money = 1000 + 100;
update user set money=1100 where id = 1;
Remittance 100 element

T5

commit;
Commit transaction    

T6

select money from user where id = 1;
Query account balance as 1000 element

        

T7

money = 1000 - 100;
update user set money=900 where id = 1;
Take out 100 Change the balance to 900 element

T8

commit;
Commit transaction

T9

Change the balance to 900  element ( Lost update )

In the above example, the deposit balance is updated because the withdrawal covers the transfer , The user lost in the end 100 element , On the contrary, if the withdrawal transaction is submitted first , Then the bank will lose 100 element .

  The second reason for missing updates :MySQL By default, snapshot reads are used for repeatable reads . Read the snapshot There is no way to obtain the latest data . Therefore, snapshot reading is a major reason for the loss of the second type of updates .

solve Read the snapshot Two basic ideas , One is pessimistic lock , The other is optimistic lock ;
Simply put, it is an assumption that such a problem is of high probability , It's best to lock it at the beginning , Lest the update always fails ; Another assumption is that such a problem is of small probability , The last step is to lock it when updating , In order to avoid locking for too long and affecting other people to do relevant operations .


Pessimistic locking

Lock when reading data , This can ensure that the data read is the latest data , And will lock the record , Other things will block if they want to get locks . So the overall business process becomes : Get the lock after opening things , Then different operations are carried out according to different business scenarios

begin;
Open transaction
begin;
Open transaction
select money from user where id = 1 for update;
Query account balance as 1000 element
select money from user where id = 1 for update;
Blocking ...
money = 1000 - 100;
update user set money=900 where id = 1;
Take out 100 Change the balance to 900 element
Blocking ...
commit; Blocking ...
Find the data :money = 900
Other operating ....

Optimism lock

add to version Field , Record the updated version of each record , Add one to the version number after each update .

Get the version number of the line before each thing starts , Bring the version number to judge when updating .update money set money = money + 100 where id = 1 and version = The version number found

select version from user where id = 1;
Get version number 0

select version from user where id = 1;
Get version number 0

begin;
Opening things

begin;
Opening things

money = 1000 - 100;
update user set money=900,version = version +1 where id = 1 and version = 0;
Take out 100 Change the balance to 900 element

The update is successful , The number of updates is 1money = 1000 + 100;
update user set money=1100,version = version +1 where id = 1 and version = 0;
Blocking ...
Blocking ...
commit
The update is successful , The number of updates is 0( Because another thing changed the version number, and now the version number is 1)

summary :

Pessimistic locking b The way is through select..for update The way , This may cause other sessions to block , Optimistic lock b Method requires maintenance of one more version column .

Personal advice : Choose pessimistic locking method in the application system with few concurrent users and serious conflicts , In other cases, first of all, optimistic locking version listing . 

原网站

版权声明
本文为[fastjson_]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/188/202207071421069832.html