Bug #102676 | In REPEATABLE READ, the behavior after executing select for update is strange. | ||
---|---|---|---|
Submitted: | 21 Feb 2021 18:29 | Modified: | 22 Feb 2021 21:03 |
Reporter: | jou jou | Email Updates: | |
Status: | Not a Bug | Impact on me: | |
Category: | MySQL Server: Locking | Severity: | S2 (Serious) |
Version: | 5.7.12, 8.0.11 | OS: | Linux (RDS of AWS) |
Assigned to: | CPU Architecture: | Any |
[21 Feb 2021 18:29]
jou jou
[22 Feb 2021 1:51]
Tsubasa Tanaka
Hi ふじもと-san, I'm from Japan MySQL User Group(I'm not Oracle person) MySQL Documentation describes, > A SELECT ... FOR UPDATE reads the latest available data, setting exclusive locks on each row it reads MySQL :: MySQL 8.0 Reference Manual :: 15.7.2.4 Locking Reads https://dev.mysql.com/doc/refman/8.0/en/innodb-locking-reads.html "latest available data" means "like a READ-COMMITTED even if transaction_isolation is REPEATABLE-READ", this is known behavior. /* from Japan MySQL User Group */
[22 Feb 2021 9:40]
jou jou
tanaka-san Thank you for your reply. I saw that page. I understood it. The difference between case1 and case2 I wrote above is, In case2, there is: mysql tx2 > select count(*) from t1; But the final result was different. Do you know the reason for this?
[22 Feb 2021 9:55]
Tsubasa Tanaka
Fujimoto-san, This is just my opinion from my experiment, (this behavior is bug or not would be decided by MySQL Verification Team.) mysql tx2 > result of *waiting* is -- by trx1> select val from t1 where id = 1 for update; +-----+ | val | +-----+ | 2 | +-----+ This is blocking-read (because, you use FOR UPDATE) and reads "latest available data" but, mysql tx2 > select val from t1 where id = 1; +-----+ | val | +-----+ | 1 | +-----+ This statement is NOT blocking read and reads depending on TRANSACTION ISOLATION LEVEL. I agree these behaviors are strange, not intuitive, and doesn't have transaction consistency, but MySQL treats like this from the old days.
[22 Feb 2021 9:56]
Tsubasa Tanaka
Fujimoto-san, This is just my opinion from my experiment, (this behavior is bug or not would be decided by MySQL Verification Team.) mysql tx2 > result of *waiting* is +-----+ | val | +-----+ | 2 | +-----+ First statement, this is blocking-read (because, you use FOR UPDATE) and reads "latest available data" but, mysql tx2 > select val from t1 where id = 1; +-----+ | val | +-----+ | 1 | +-----+ Second statement is NOT blocking read and reads depending on TRANSACTION ISOLATION LEVEL. I agree these behaviors are strange, not intuitive, and doesn't have transaction consistency, but MySQL treats like this from the old days.
[22 Feb 2021 10:22]
jou jou
tanaka-san Thank you very much. >MySQL treats like this from the old days. I was a little relieved to hear this. I was really worried about unexplained behaviors. I found a similar behaviors, so I'll share it. [case1] mysql tx1 > use db1; mysql tx2 > use db1; mysql tx1 > select count(*) from t1 where id = 1; +----------+ | count(*) | +----------+ | 1 | +----------+ mysql tx1 > begin; mysql tx2 > begin; mysql tx1 > insert into t1 (id, val) values (1, 123); mysql tx1 > commit; mysql tx2 > select count(*) from t1 where id = 1; +----------+ | count(*) | +----------+ | 2 | +----------+ This is right. [case2] mysql tx1 > use db1; mysql tx2 > use db1; mysql tx1 > select count(*) from t1 where id = 1; +----------+ | count(*) | +----------+ | 1 | +----------+ mysql tx1 > begin; mysql tx2 > begin; mysql tx2 > select count(*) from t2; mysql tx1 > insert into t1 (id, val) values (1, 123); mysql tx1 > commit; mysql tx2 > select count(*) from t1 where id = 1; +----------+ | count(*) | +----------+ | 1 | +----------+ This is strange. The difference between case1 and case2 I wrote above is, In case2, there is: mysql tx2 > select count(*) from t2; I am grateful for your quick reply.
[22 Feb 2021 14:06]
MySQL Verification Team
Hi Mr. jo, Thank you very much for your bug report. However, this is not a bug. Mr. Tanaka is quite right in his analysis. Let me add, that in all MVCC engines, the current view must be respected, regardless of what other sessions are doing. This is a reason why we have lock waits, mutex waits, and all kind of locking, like S, SX etc ..... In your case, count is different, because the other row is not visible to other sessions. Not a bug.
[22 Feb 2021 14:36]
Tsubasa Tanaka
@MySQL Verification Team > that in all MVCC engines, the current view must be respected, Yes. So why "locking-read statement reads latest available data?", why "locking-read statement is not honest its transaction isolation level?" I think this report indicates this point. (My explanation, "That is MySQL way", does not explain the reason why at all)
[22 Feb 2021 21:03]
jou jou
@MySQL Verification Team tanaka-san Thank you for confirmation. I understood it.