-
Notifications
You must be signed in to change notification settings - Fork 3.9k
storage: Handle timestamp collisions in timestampCache #9100
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
Conversation
Reviewed 4 of 4 files at r1, 2 of 2 files at r2. storage/timestamp_cache.go, line 436 [r1] (raw file):
You didn't touch this, but we might want to improve the name of this flag. storage/timestamp_cache.go, line 442 [r1] (raw file):
storage/timestamp_cache.go, line 451 [r1] (raw file):
It would be nice to alias
storage/timestamp_cache.go, line 223 [r2] (raw file):
It would be nice to have a storage/timestamp_cache.go, line 337 [r2] (raw file):
storage/timestamp_cache.go, line 346 [r2] (raw file):
This shouldn't be needed, because the entry isn't getting a new timestamp, right? storage/timestamp_cache.go, line 370 [r2] (raw file):
Is:
needed here? This should be the last overlap. storage/timestamp_cache.go, line 383 [r2] (raw file):
Can we define this storage/timestamp_cache.go, line 409 [r2] (raw file):
Nit: I like how this diagram defines all three (New, Nil, and Old). Could we do that for all (maybe with Nil using a different symbol like storage/timestamp_cache.go, line 425 [r2] (raw file):
Can we rename this variable, it confused me for a little while because I didnt see the storage/timestamp_cache.go, line 426 [r2] (raw file):
Again, we might want to define this above? See comment on line 383. Here we could just reassign the value if we need to mutate it. storage/timestamp_cache.go, line 431 [r2] (raw file):
Here and in a few other states ( This means we might want storage/timestamp_cache.go, line 458 [r2] (raw file):
storage/timestamp_cache.go, line 460 [r2] (raw file):
Really? Won't this be guaranteed to be the last overlap? Comments from Reviewable |
For my own edification, would you mind explaining why we need to nil out the span's owner rather than letting the transaction that got there first maintain ownership of it? What would be the harm in letting the "first" transaction finish as long as we prevented the other transactions from continuing with the same timestamp? |
Review status: 3 of 4 files reviewed at latest revision, 14 unresolved discussions. storage/timestamp_cache.go, line 436 [r1] (raw file):
|
Would you mind explaining why we need to nil out the span's owner rather than letting the transaction that got there first maintain ownership of it? What would be the harm in letting the "first" transaction finish as long as we prevented the other transactions from continuing with the same timestamp? I assume there will be cases in which the "first" transaction is already done by the time the "second" one sees the cache entry anyway. Review status: 3 of 4 files reviewed at latest revision, 14 unresolved discussions, some commit checks failed. Comments from Reviewable |
In this case the two transactions are read-only at the time of the conflict (they go on to write later). We can't require that all read-only transactions have unique timestamps (think of time-travel queries), so we have to allow the reads to proceed and deal with the overlap if and only if they later issue a conflicting write. |
Reviewed 4 of 4 files at r1, 2 of 2 files at r2, 1 of 1 files at r3, 1 of 1 files at r4. storage/timestamp_cache.go, line 416 [r1] (raw file):
From the comment, I'm not clear on what the last part means. storage/timestamp_cache.go, line 339 [r2] (raw file):
Comments from Reviewable |
Reviewed 1 of 1 files at r4. storage/timestamp_cache.go, line 354 [r4] (raw file):
For this case and the next, cant we just delete old and extend new's bounds to avoid multiple entries? Comments from Reviewable |
Review status: all files reviewed at latest revision, 4 unresolved discussions, some commit checks failed. storage/timestamp_cache.go, line 354 [r4] (raw file):
|
Review status: all files reviewed at latest revision, 4 unresolved discussions, some commit checks failed. storage/timestamp_cache.go, line 354 [r4] (raw file):
|
timestampCache.GetMax{Read,Write} previously took a transaction ID to act as that transaction. However, this wasn't always correct - when acting as a transaction we look past that transaction's writes to see what's underneath, but the trimming of inserted spans means that this would often return the low water mark, ignoring spans that had been present but were trimmed away. Instead, the timestamp cache now returns the transaction associated with the timestamp it is returning, so the caller can make its own decision about whether to ignore the timestamp or not.
When two intervals in the timestamp cache have the same timestamp, neither of them can be said to own that timestamp. We must adjust intervals and clear transaction IDs whenever this collision occurs. Failure to do so allowed one transaction to write after another transaction had read at the same timestamp, leading to a violation of serializability. Fixes cockroachdb#9083
When intervals have both the same timestamp and transaction ID (which is fairly common since this is what happens whenever a transaction touches the same rows more than once), we can avoid the splitting required when timestamps are equal but transaction IDs differ. Introduce (simple) special cases for this scenario.
30514de
to
27a521e
Compare
27a521e
to
581caf0
Compare
When two intervals in the timestamp cache have the same timestamp,
neither of them can be said to own that timestamp. We must adjust
intervals and clear transaction IDs whenever this collision occurs.
Failure to do so allowed one transaction to write after another
transaction had read at the same timestamp, leading to a violation of
serializability.
Fixes #9083
@cockroachdb/stability @nvanbenschoten
This change is