The thing is about a very simple update statement:
UPDATE `user` SET fans = fans +1 where id = 8;
(because it will not cause any concurrency issue when just single[auto commit] use it, so I want to figure it out how it behaves in a manual transaction.) And it turns out that this statement seems to break the limitations of RR's isolation level in a transaction.
Let's assume that fans = 0.
That is:
user
WHERE id = 8;", and hold. (the query gets fans = 0);user
SET fans = fans +1 where id = 8, and Commit.user
WHERE id = 8;" , again, in tran A, and the result of fans is 0, it meets expectation. (because we are in RR, should not see any updates after our transaction begin.)user
SET fans = fans +1 where id = 8;" In tran A, and use "SELECT * from user
WHERE id = 8;" again, we can see that 'fans' field is updated to 2.
It seems that is an RC behavior, not an RR hehavior. (but 'SELECT @@transaction_isolation;' says it is in 'REPEATABLE-READ').My mysql version is '8.0.41-0ubuntu0.22.04.1', isolation is 'REPEATABLE-READ', engine is Innodb.
So I assume, that is a special-designed feature for the 'self-increment statement', or it is something go wrong? I am not an expert so I am very confused, looking forward for any insight of this.
Your expectation regarding the behaviour of repeatable read after an update is not correct. In repeatable read isolation level insert / update / delete operations still work with committed versions of rows.
Since the result of the update statement in transaction A is fans = 2
, and repeatable read does reflect changes done by the current transaction to the resultset, the subsequent select in transaction A also correctly reflects fans = 2
.
To conclude that this is the correct behaviour, just imagine that
This table represented current account balances at a bank
Row with id = 8
was your current account balance
These two transactions represented incoming payments crediting money to your account.
What would you like your balance be after the two transactions?