September 14, 2017·4 min read·engineeringcockroachdbmvcccorrectnessstorage

CockroachDB 1.0.6 repairs reverse scans that could omit rows

Reverse scans could stop too early while looking for historical values. CockroachDB 1.0.6 repairs scan logic, includes a RocksDB corruption fix, and disables parallel statement execution by default.

An empty result does not tell an application whether no matching row exists or the database stopped scanning too early. CockroachDB 1.0.6 fixes reverse-scan defects that could omit data from query results. One correction concerns a scan for a value at a particular timestamp reaching the end of a key range. That condition incorrectly stopped a broader backward scan.

The September 14 release notes also include a potential RocksDB data-corruption fix. Those are distinct failure classes. A query can omit a stored row because traversal is wrong without the underlying row being physically corrupted. Keeping that difference explicit matters when interpreting what the update repairs.

I value the strong consistency model in CockroachDB, but useful results also require correct traversal of the versions stored underneath SQL. A transaction can follow an intended isolation policy and still receive an incomplete result if a scan ends at the wrong boundary. This release addresses that lower-level path directly.

A timestamp lookup is not the entire reverse scan

The MVCC correction, merged August 24, explains the first defect. mvccGetInternal could scan off the end of a key range while searching for a value at a particular timestamp. MVCCReverseScan should then continue backward instead of treating that local outcome as the end of its work.

The fix delays acting on iterator validity until the iterator has scanned to the previous key. That preserves the distinction between failing to find an appropriate value in one lookup and having no earlier keys left to visit. An iterator state observed inside the lookup did not establish that the enclosing reverse scan was complete.

This is a concrete interaction between version selection and traversal. Finding the version visible at a timestamp is one task. Moving backward through keys is another. Allowing the former task's boundary condition to terminate the latter can silently remove rows from the result.

The implementation description supplies the mechanism without requiring a claim that all reverse scans fail. A problematic execution needs the timestamp lookup and range-boundary interaction. The release's broader wording, data could be missing from query results, describes the application-visible consequence of that narrower internal condition.

Backward batch boundaries also needed correction

A second reverse-scan backport, merged September 9, corrects the prev() helper. Its description identifies an off-by-one error and another path that assembled a return value from start keys instead of end keys. Those mistakes computed the wrong boundary for remaining work.

The pull request gives an example where keys at or above a later boundary have already been handled, leaving a half-open interval to scan. Returning that interval's start instead of its end does not identify the next correct backward position. The traversal can skip the work it should still perform.

Both corrections concern scan progress, but they operate at different places. One prevents an inner timestamp lookup from ending a larger scan. The other computes where backward work should continue across a remaining batch. A broad statement that reverse scanning was fixed is accurate but leaves out why multiple code changes were necessary.

I find this distinction useful when reading maintenance notes because a query result depends on several nested iteration decisions. Correctness requires each layer to preserve the amount of work remaining. A boundary value that is valid for one layer can be wrong when interpreted by another.

The storage fix includes a dependency regression guard

The RocksDB backport describes reproducing a DeleteRange bug and manually applying the correction to CockroachDB's RocksDB repository. Its test is intended to prevent a later dependency update from adopting a version without the fix.

That is a separate concern from SQL result traversal. The release notes call it potential data corruption, while the backport identifies the storage operation involved. Neither source gives a general repair procedure for all existing data, so the update should not be described as proving every previously stored byte valid.

The regression guard also makes dependency management part of maintaining the correction. Importing another storage-engine revision must preserve the behavior already fixed. The test records a required property of that dependency, beyond merely naming a new version.

Parallel statement execution is disabled by default

The same release disables parallel statement execution by default because of problems handling retryable errors. That changes the default introduced for eligible writes earlier in development. The release does not present parallelism as more important than correctly handling transaction retries.

Other fixes prevent dangerously small kv.raft.command.max_size settings and correct a range-lease issue that could make ranges unavailable. These concern operational bounds and availability. For query correctness, the most concrete changes are the repaired reverse-scan continuation rules and the storage dependency correction, each with a different failure mechanism and a distinct reason to be included in the maintenance release.