Add cluster-wide read-only status variable
- 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
Assessment
This issue has not been assessed yet.