Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

strange behavior when begin transaction when 'tidb_snapshot' is set #25176

Open
lcwangchao opened this issue Jun 4, 2021 · 6 comments
Open
Labels
severity/moderate sig/transaction SIG:Transaction type/bug The issue is confirmed as a bug.

Comments

@lcwangchao
Copy link
Collaborator

Bug Report

Please answer these questions before submitting your issue. Thanks!

1. Minimal reproduce step (Required)

s1, and s2 are two tidb connections.

s1 s2
create table test.ttt (id int primary key, a int);
insert into test.ttt values(1, 1);
begin;
update test.ttt set a=2 where id=1;
do sleep(1);set @@tidb_snapshot=TIMESTAMP(NOW());
select a from test.ttt where id=1;
select a from test.ttt where id=1 for update;
select a from test.ttt where id=1;

2. What did you expect to see? (Required)

mysql> select a from test.ttt where id=1;
+------+
| a    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)
mysql> select a from test.ttt where id=1 for update;
+------+
| a    |
+------+
|    2 |
+------+
1 row in set (0.00 sec)
mysql> select a from test.ttt where id=1;
+------+
| a    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

3. What did you see instead (Required)

mysql> select a from test.ttt where id=1;
+------+
| a    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)
mysql> select a from test.ttt where id=1 for update;
+------+
| a    |
+------+
|    2 |
+------+
1 row in set (0.00 sec)
mysql> select a from test.ttt where id=1;
+------+
| a    |
+------+
|    2 |
+------+
1 row in set (0.00 sec)

4. What is your TiDB version? (Required)

master

@lcwangchao lcwangchao added the type/bug The issue is confirmed as a bug. label Jun 4, 2021
@lcwangchao
Copy link
Collaborator Author

@cfzjywxk PTAL

@lcwangchao
Copy link
Collaborator Author

It seems when building a executor, getSnapshotTs's return uses sys var 'SnapshotTS' once it isset ignoring the txn's startTs.

tidb/executor/builder.go

Lines 1397 to 1404 in fbbada3

snapshotTS := b.ctx.GetSessionVars().SnapshotTS
if snapshotTS == 0 {
txn, err := b.ctx.Txn(true)
if err != nil {
return 0, err
}
snapshotTS = txn.StartTS()
}

And when opening PointGetExecutor, it will step to line 135 if for update read ts is bigger than txn read ts, thats why it only happends after a select ... for update clause.

tidb/executor/point_get.go

Lines 132 to 136 in fbbada3

if e.txn.Valid() && txnCtx.StartTS == txnCtx.GetForUpdateTS() {
e.snapshot = e.txn.GetSnapshot()
} else {
e.snapshot = e.ctx.GetStore().GetSnapshot(kv.Version{Ver: snapshotTS})
}

@cfzjywxk
Copy link
Contributor

cfzjywxk commented Jun 6, 2021

It seems when building a executor, getSnapshotTs's return uses sys var 'SnapshotTS' once it isset ignoring the txn's startTs.

tidb/executor/builder.go

Lines 1397 to 1404 in fbbada3

snapshotTS := b.ctx.GetSessionVars().SnapshotTS
if snapshotTS == 0 {
txn, err := b.ctx.Txn(true)
if err != nil {
return 0, err
}
snapshotTS = txn.StartTS()
}

And when opening PointGetExecutor, it will step to line 135 if for update read ts is bigger than txn read ts, thats why it only happends after a select ... for update clause.

tidb/executor/point_get.go

Lines 132 to 136 in fbbada3

if e.txn.Valid() && txnCtx.StartTS == txnCtx.GetForUpdateTS() {
e.snapshot = e.txn.GetSnapshot()
} else {
e.snapshot = e.ctx.GetStore().GetSnapshot(kv.Version{Ver: snapshotTS})
}

@lcwangchao
Thanks for the feedback, the behaviour is strange and we'll disscuss about the tidb_snapshot variable when it's used with the pessimistic transaction.

@cfzjywxk
Copy link
Contributor

cfzjywxk commented Jun 10, 2021

/cc
@jackysp @MyonKeminta
We may need to discuss about this behaviour setting snapshot ts during transaction execution. For pessimistic transactions, if the snapshot is set and other features like read-committed is used, I'm afraid there could be unexpected behaviours or possbile risks.

@jackysp
Copy link
Member

jackysp commented Jun 10, 2021

I think we should narrow down the scope of tidb snapshot.

@MyonKeminta
Copy link
Contributor

I agree to limit the usage of this variable. IMHO it should never be used with transactions. But limiting its usage can potentially cause compatibility issues between new and old versions of TiDB.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
severity/moderate sig/transaction SIG:Transaction type/bug The issue is confirmed as a bug.
Projects
None yet
Development

No branches or pull requests

5 participants