January 31, 2025·4 min read·engineeringcockroachdbmetadatareliability

CockroachDB 24.3.4 refreshes stale reads during schema introspection

A cached timestamp could make SHOW TABLES read before the replica's garbage-collection threshold. January's patch refreshes the cache and retries with a newer timestamp.

Listing tables can fail for reasons that have little to do with whether those tables exist. CockroachDB 24.3.4 fixes an introspection path that could read metadata using a timestamp older than a replica's garbage-collection threshold. The January 31 release notes identify SHOW TABLES and related operations as affected.

The distinction matters for tools that discover a schema before doing anything else. A database can be reachable while a metadata operation fails, and the resulting client error can look like a broader inability to inspect or use the database. The patch addresses timestamp selection inside that discovery path.

I accept CockroachDB's visible coordination costs because its serializable model supplies useful consistency guarantees. That preference includes understanding the temporal assumptions beneath ordinary SQL. An introspection statement still depends on the versioned data and metadata that the distributed engine makes available.

The reported failure included role lookup

The January issue report describes failures in the console SQL shell and other SQL clients. Its error includes read-roles and says the batch timestamp must be after the replica GC threshold. The report's example used a batch timestamp older than the threshold, so the storage rejection was consistent with the timestamps in the message.

The report also says the behavior was not uniform across client contexts. On an affected cluster it could appear after waiting, and the reporter did not initially know all environmental conditions required to reproduce it. These are observations from that report, not claims about every deployment.

That variability makes the error easy to misclassify as a client problem. The client executes a familiar statement, but an internal role lookup encounters the unusable timestamp. Changing the visible table-listing query does not necessarily change the cached state that selected the internal read time.

MVCC retains history for a bounded period

CockroachDB's storage-layer documentation explains that MVCC distinguishes data versions by timestamp. Old versions support consistent historical reads, but the engine garbage-collects eligible versions to reduce stored data. Schema information also has a versioned model so that historical queries can use the corresponding schema.

This means that an old timestamp is a request with storage consequences. Once the relevant history is outside the retained interval, the engine cannot treat the request as if it were a current read. Rejecting it preserves the distinction between a snapshot the database can supply and one it cannot.

The AS OF SYSTEM TIME reference makes that limit visible to SQL users. Historical data is available within the garbage-collection window. Explicit time-travel queries therefore have to choose a time for which the database still retains usable history.

The introspection defect differs from an application intentionally asking for an unavailable historical snapshot. The visible operation requests schema information, while internal cached state supplies an old read timestamp. January's patch corrects that internal choice when storage reports the timestamp problem.

The retry changes the state that caused failure

The release backport explains the correction. On a timestamp error, the implementation marks the cache stale, releases the lease and retries. This causes a newer read timestamp to be used and refreshes the cache on its next access.

That is more specific than repeating the identical failed operation. A retry that reused the same old timestamp would still conflict with the same GC threshold. Invalidating the cached state changes the conditions of the next attempt, which is the necessary part of recovery here.

The published change does not extend the historical retention period. It does not ask storage to return versions that have already become unavailable. Instead, it makes the metadata path stop relying on an obsolete timestamp when it encounters this error.

Schema discovery is part of application availability

The SHOW TABLES reference documents output including schema, table name, type and owner, with estimated row-count information. It supports choosing a database and schema, which lets a tool discover objects beyond its current default context.

The relevant SQL can be small even though the internal operation crosses several concerns. For a database named app, an ordinary introspection statement is:

SHOW TABLES FROM app.public;

This example describes the user-visible command, not a deterministic reproducer for the cache bug. The original issue itself reports context-dependent behavior. A test that only proves a connection can execute a trivial expression would not exercise the same discovery path.

I find this patch useful because it repairs an operationally common command without weakening the storage rule that rejected the old read. Tools depend on metadata access to decide what queries to issue next. In 24.3.4, the affected lookup can recover by refreshing the state that selected the expired timestamp, allowing introspection to proceed with a newer read.