Cluster recovery degradation after restart when `pd-store-heartbeat-tick-interval` is reduced from 10s to 5s
- Dominant language
- Go
- Stars
- 40.5k
- Forks
- 6.2k
- PR merge metrics
- PR metrics pending
Description
# Cluster recovery degradation after restart when `pd-store-heartbeat-tick-interval` is reduced from 10s to 5s
## Summary
I observed a recovery/degradation problem after a management restart with a valid configuration change. The baseline cluster and the changed-config cluster were set up with the same topology and were run through the same basic SQL workload and recovery observation flow. The changed-config cluster was expected to become healthy again after the restart window, but it remained unhealthy while the baseline side was classified as healthy.
This report is about recovery/availability rather than confirmed data corruption. The reason I consider it worth tracking is that the configuration value is a normal TiDB/TiKV configuration value, and restart/rejoin should not leave the cluster persistently degraded under this small workload.
## Environment
- TiDB/TiKV/PD version observed from PD store status: `8.5.6`
- Deployment shape: two independent local clusters
- Topology per cluster: 1 PD, 2 TiDB servers, and 3 TiKV stores per cluster
- Comparison style: same workload and recovery observation, different configuration value only
## Configuration difference
```text
Component: tikv
Parameter: raftstore.pd-store-heartbeat-tick-interval
Baseline: 10s
Changed: 5s
```
Effective configuration shape:
```toml
# baseline cluster
[raftstore]
pd-store-heartbeat-tick-interval = "10s"
# comparison cluster
[raftstore]
pd-store-heartbeat-tick-interval = "5s"
```
## Reproduction flow
1. Start two independent TiDB clusters with the topology above.
2. Keep one cluster on the baseline configuration.
3. Start the other cluster with the changed configuration shown above.
4. Verify both clusters are healthy before the restart step.
5. Run a small SQL workload on both clusters.
6. Trigger the management restart/recovery operation.
7. Wait for the normal recovery/rejoin window.
8. Query SQL health and PD health/store status.
9. Compare the final health classification of the two clusters.
Operation used during the run:
```text
A PD store-status request was issued at the same point in both clusters, for example `GET /pd/api/v1/stores`. This should only inspect PD's view of store state and should not alter SQL data.
```
Workload summary:
```text
The SQL part is intentionally small in this reproduction: 3 statements creating one table, inserting one row, and reading it back.
```
## Expected behavior
Both clusters should recover after the restart/rejoin window. A valid configuration change may alter heartbeat frequency, store refresh latency, or recovery timing, but it should not leave the changed-config cluster persistently unhealthy after the same management restart flow.
Expected health before the operation:
```text
baseline cluster healthy: True
changed-config cluster healthy: True
```
## Actual behavior
Final health classification after the operation:
```text
baseline cluster healthy: True
changed-config cluster healthy: False
```
Additional observation:
```text
A later health snapshot showed PD reachable on the changed-config cluster, but SQL health checks failed with `ERROR 2003 (HY000): Can't connect to MySQL server on '127.0.0.1:3306' (111)`. The control/changed cluster classification at the failure point was healthy/unhealthy respectively.
```
The comparison immediately before this failure point had the same input properties:
```text
only the configuration value differed: True
same workload: True
same initial data state: True
same timing plan: True
same cluster action template: True
same observation query: True
previous data-state hash, baseline: 41ef43db29b3bba95450908c9c0b29eebc0e5936bb720d8a5a0513050cf3aa71
previous data-state hash, changed: 41ef43db29b3bba95450908c9c0b29eebc0e5936bb720d8a5a0513050cf3aa71
```
## SQL workload used in the recovery check
```sql
CREATE TABLE IF NOT EXISTS t_replay (id INT PRIMARY KEY, val VARCHAR(100)) ENGINE=TiDB;
INSERT INTO t_replay VALUES (1, 'replay_test');
SELECT * FROM t_replay;
```
## Health checks used
```bash
# SQL reachability
mysql -h -P 4000 -u -p -e "SELECT 1 AS health_check;"
# PD member health
curl -fsS http://:2379/pd/api/v1/health
# PD store view
curl -fsS http://:2379/pd/api/v1/stores
```
## Why this looks relevant
The failure is not caused by changing the SQL workload. The SQL part is intentionally simple, and the comparison point was designed to isolate the configuration/recovery behavior. The most likely area to inspect is the component that consumes the changed setting and its interaction with restart/rejoin logic, PD store state, TiDB store-cache refresh, or TiKV heartbeat propagation.
## Suggested area to inspect
- whether the changed setting can delay or suppress store-state refresh after restart;
- whether PD marks stores as disconnected for longer than expected;
- whether TiDB SQL nodes keep stale store status after restart;
- whether the recovery path has a race between restart completion and store/region health observation.
Contributor guide
Research direction
Start by reproducing the restart flow and running the listed SQL health check plus the PD `/pd/api/v1/health` and `/pd/api/v1/stores` endpoints around recovery. Inspect how `raftstore.pd-store-heartbeat-tick-interval` interacts with PD store state, TiDB store-cache refresh, and TiKV heartbeat propagation. Done means both clusters recover and the changed configuration does not leave SQL unreachable or classified unhealthy.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, sql
- Domain
- backend, databases, distributed-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100