pingcap / pingcap/tidb

Add cluster-wide read-only status variable

Open
#68,852 0 comments 0 reactions 0 assignees View on GitHub
type/feature-request
Dominant language
Go
Stars
40.5k
Forks
6.2k
PR merge metrics
PR metrics pending

Description

## Feature Request

**Is your feature request related to a problem? Please describe:**

TiDB currently has read-only related global variables such as `tidb_restricted_read_only` and `tidb_super_read_only`, but there is no single SQL-visible indicator that confirms the whole TiDB cluster is effectively running in read-only mode.

Checking `mysql.global_variables` only shows the intended persisted global value. It does not prove that every TiDB instance has already applied the value in memory. Querying `@@global.tidb_restricted_read_only` or `@@global.tidb_super_read_only` through a load balancer also only proves the state of the TiDB instance that handled that query.

This makes operational checks harder during maintenance, failover, incident handling, or controlled read-only transitions. Operators need a reliable way to know when all TiDB instances are enforcing read-only behavior.

**Describe the feature you'd like:**

Introduce a read-only system/status variable, tentatively named `tidb_is_read_only`, that returns `ON` only when all live TiDB instances report effective read-only state.

Suggested semantics:

- The variable itself is read-only and cannot be set by users.
- A TiDB instance is considered effectively read-only when:

```text
tidb_restricted_read_only = ON OR tidb_super_read_only = ON
```

- `tidb_is_read_only = ON` only when every live TiDB instance reports a fresh local effective read-only status.
- If any live TiDB instance reports `OFF`, is missing, unreachable, or has stale status, the aggregate value should conservatively return `OFF`.

Example user-facing behavior:

```sql
SELECT @@global.tidb_is_read_only;
```

returns:

```text
ON
```

only after every live TiDB instance has applied effective read-only mode.

It would also be useful to expose the per-instance source data for troubleshooting, for example through an `INFORMATION_SCHEMA` table or metric:

```text
instance
tidb_restricted_read_only
tidb_super_read_only
effective_read_only
last_update_time
```

This lets users understand which TiDB instance prevents the aggregate value from becoming `ON`.

**Describe alternatives you've considered:**

1. Manually enumerate all TiDB instances and connect to each SQL port directly:

```sql
SELECT @@global.tidb_restricted_read_only,
@@global.tidb_super_read_only;
```

This works, but it is manual, error-prone, and inconvenient for automation.

2. Query `mysql.global_variables`.

This is not sufficient because it only shows persisted intent. It does not prove every TiDB process has applied the value in memory.

3. Add only a Prometheus metric.

A per-instance metric such as `tidb_server_read_only_status{type="restricted|super|effective"}` would be useful for alerting, but a SQL-visible variable/status is still useful for operational runbooks and interactive checks.

**Teachability, Documentation, Adoption, Migration Strategy:**

This should be documented as a derived cluster-wide status, not a configurable setting.

The documentation should clarify that `tidb_is_read_only=ON` means normal user writes are blocked cluster-wide. It does not mean every possible internal write path is disabled. Internal/restricted SQL and users with explicit bypass privileges such as `RESTRICTED_REPLICA_WRITER_ADMIN` can still write by design.

There is no migration requirement. Existing variables such as `tidb_restricted_read_only` and `tidb_super_read_only` should keep their current behavior. The new variable/status only provides a safer aggregate observability surface.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.