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

storage: allow HeartbeatTxn and EndTxn requests to create txn records #33396

Merged
merged 5 commits into from
Jan 7, 2019

Commits on Jan 7, 2019

  1. storage: remove VersionClientSideWritingFlag

    The setting is baked into 2.2 binaries.
    
    Release note: None
    nvanbenschoten committed Jan 7, 2019
    Configuration menu
    Copy the full SHA
    96b552a View commit details
    Browse the repository at this point in the history
  2. storage: move tscache-related methods to new file

    Updating and applying the timestamp cache are two sides of the same
    coin. It makes sense that these methods should live right next to
    each other.
    
    Release note: None
    nvanbenschoten committed Jan 7, 2019
    Configuration menu
    Copy the full SHA
    5110516 View commit details
    Browse the repository at this point in the history
  3. storage: remove setTxnAutoGC(true) in tests

    The global defaults to true.
    
    Release note: None
    nvanbenschoten committed Jan 7, 2019
    Configuration menu
    Copy the full SHA
    ab4dffb View commit details
    Browse the repository at this point in the history
  4. roachpb: ignore error timestamp when restarting aborted txn

    The local hlc should have been advanced to at least the error's
    timestamp by the time PrepareTransactionForRetry is called.
    
    Release note: None
    nvanbenschoten committed Jan 7, 2019
    Configuration menu
    Copy the full SHA
    7472973 View commit details
    Browse the repository at this point in the history
  5. storage: allow HeartbeatTxn and EndTxn requests to create txn records

    Informs cockroachdb#25437.
    Informs cockroachdb#32971.
    
    This is the first part of addressing cockroachdb#32971. Part two will update
    concurrent txns to not immediately abort missing txn records and
    part three will update the txn client to stop sending BeginTxn
    records.
    
    The change closely resembles what was laid out in the corresponding
    RFC sections. `HeartbeatTxn` and `EndTxn` are both updated to permit
    the creation of transaction records when they finds that one is missing.
    
    To prevent replays from causing issues, they *both* check the write
    timestamp cache when creating a transaction record. This is one area
    where the change diverges from the RFC. Instead of having `EndTxn`
    always check the write timestamp cache, it only does so if it is
    creating a txn record from scratch. To make this safe, `HeartbeatTxn`
    also checks the write timestamp cache if it is creating a txn record
    from scratch. This prevents a long running transaction from increasingly
    running the risk of being aborted by a lease transfer as its `EndTxn`
    continues to be delayed. Instead, a lease transfer will only abort a
    transaction if it comes before the transaction record creation, which
    should be within a second of the transaction starting.
    
    The change pulls out a new `CanCreateTxnRecord` method, which has the
    potential of being useful for detecting eagerly GCed transaction records
    and solving the major problem from the RFC without an extra QueryIntent.
    This is what Andrei was pushing for before. More details are included
    in TODOs within the PR.
    
    _### Migration Safety
    
    Most of the changes to the transaction state machine are straightforward
    to validate. Transaction records can still never be created without
    checking for replays and only an EndTxn from the client's sync path
    can GC an ABORTED txn record. This means that it is still impossible for
    a transaction to move between the two finalized statuses (at some point
    it would be worth it to draw this state machine).
    
    The one tricky part is ensuring that the changes in this PR are safe
    when run in mixed-version clusters. The two areas of concern are:
    1. lease transfers between a new and an old cluster on a range that
    should/does contain a transaction record.
    2. an old txn client that is not expecting HeartbeatTxn and EndTxn
    requests to create txn records if they are found to be missing.
    3. an old txn client may not expect a HeartbeatTxn to hit the
    write timestamp cache if run concurrently with an EndTxn.
    
    The first concern is protected by the write timestamp cache. Regardless
    of which replica creates that transaction record from a BeginTxn req or
    a HeartbeatTxn req (on the new replica), it will first need to check
    the timestamp cache. This prevents against any kind of replay that could
    create a transaction record that the old replica is not prepared to
    handle.
    
    We can break the second concern into two parts. First, an old txn client
    will never send an EndTxn without having sent a successful BeginTxn, so
    the new behavior there is not an issue. Second, an old txn client may
    send a HeartbeatTxn concurrently with a BeginTxn. If the heartbeat wins,
    it will create a txn record on a new replica. If the BeginTxn evaluates
    on a new replica, it will be a no-op. If it evaluates on an old replica,
    it will result in a retryable error.
    
    The third concern is specific to the implementation of the heartbeat loop
    itself. If a HeartbeatTxn loses a race with an EndTxn, it may get an
    aborted error after checking the timestamp cache. This is desirable from
    the replica-side, but we'd need to ensure that the client will handle it
    correctly. This PR adds some protection (see `sendingEndTxn`) to the txn
    client to prevent this case from causing weirdness on the client, but I
    don't think this could actually cause issues even without this protection.
    The reason is that the txn client might mark itself as aborted due to the
    heartbeat, but this will be overwritten when the EndTxn returns and the sql
    client will still hear back from the successful EndTxn. This must have
    actually always been an issue because it was always possible for a committed
    txn record to be GCed and then written as aborted later, at which point a
    concurrent heartbeat could have observed it.
    
    I'd like Andrei to sign off on this last hazard, as he's thought about
    this kind of thing more than anybody.
    
    Release note: None
    nvanbenschoten committed Jan 7, 2019
    Configuration menu
    Copy the full SHA
    8143b45 View commit details
    Browse the repository at this point in the history