CockroachDB 1.0.4 orders lease handoff after read-history updates
A lease-transfer race let requests run before the new holder accounted for earlier reads. CockroachDB 1.0.4 corrects that ordering to preserve serializability.
Handing responsibility for requests to another replica also requires handing over the information that constrains those requests. CockroachDB 1.0.4 fixes a race where a replica could begin processing work under its new lease before accounting for reads served by the previous lease holder. The missing ordering could violate serializability even though the lease itself had changed successfully.
The July 27 release notes describe the defect as requests racing with lease transfer. The implementation correction, merged July 20, identifies the specific sequence of in-memory updates. This is a small maintenance release with a correction to a central consistency guarantee.
I value CockroachDB's serializable default because it gives applications a strong model for concurrent work. That guarantee depends on coordination code below SQL as well as the transaction executor. This fix shows why a successful leadership or lease transition cannot be evaluated independently of the read history it must preserve.
The old ordering exposed an incomplete handoff
Before the correction, the implementation updated a replica's in-memory lease, released its lock, and then updated the timestamp cache. Releasing the lock allowed the replica to start processing requests. At that moment, the timestamp cache could still lack information about reads handled by the old lease holder.
The implementation description states the consequence directly. The new holder could serve requests without first taking those earlier reads into account. A new lease gave it permission to process work, but the associated state was not yet ready for that work to preserve the intended ordering.
This is a race between two parts of one transition. Updating each piece eventually is insufficient when another request can observe the intermediate state. The dangerous interval lies after request processing becomes possible and before the cache reflects the history that processing needs.
The correction updates the timestamp cache before updating the lease. It changes when the new holder can expose its authority relative to the supporting state. Requests can no longer enter through the same interval with a current lease and an incomplete account of earlier reads.
The failure appeared as duplicate application values
The pull request describes reproducing the issue with a concurrent SQL logic test. The test expected inserted values to increase monotonically, but the race could produce duplicates. After the ordering change, that test passed.
This is more informative than describing the defect solely as a lock problem. The implementation's scheduling mistake reached an observable database result. The test's expected ordering represented an application-level property, while the fix concerned the sequence of lease and cache updates underneath it.
The reproduction does not establish how frequently an arbitrary application would encounter the race. It establishes that the implementation admitted an execution violating the expected property. The release notes appropriately identify possible serializability violations without attaching an unsupported production incident rate.
I find that relationship between test and mechanism useful. A consistency failure can arise from a short concurrency window that ordinary sequential SQL testing never exercises. Explaining which state becomes visible too early gives the observed duplicate values a specific cause.
A split is not always a lease transfer
The same correction updates split handling to pass the current lease as the previous lease to the lease-application routine. The stated purpose is to avoid updating the timestamp cache when the lease has not actually changed hands. That prevents the repair from treating every call through related code as a new handoff.
This qualification matters because common routines can serve several state transitions. The code needs to know whether it is applying a real change in holder or preserving the same lease during another operation. Correctness requires both the right update order and an accurate description of the transition taking place.
A broader claim that every split changes lease ownership would therefore be wrong. The implementation note explicitly handles a case where no such transfer happened. Keeping that distinction preserves the mechanism the fix actually addresses.
Transaction recovery also becomes more permissive
Version 1.0.4 accepts ROLLBACK TO SAVEPOINT more broadly. The associated backport describes accepting it after any error. That is a transaction-control compatibility change separate from the lease race, even though both affect how applications proceed under concurrency and failure.
The beta-to-production transaction model still needs its documented retry protocol. Accepting a rollback command in more states should not be expanded into a claim that every savepoint feature or nested transaction is supported. The release notes name a specific accepted operation.
Other repairs include boolean values in CREATE TABLE AS SELECT and special-character column names in schema-related statements. Those affect ordinary SQL behavior. The lease-transfer fix is more fundamental to concurrent execution, ensuring that the replica's read-history state is ready before its new lease enables it to serve requests.