MView: MLOG stats_meta.count drifts upward again after purge even after auto analyze
- Dominant language
- Go
- Stars
- 40.5k
- Forks
- 6.2k
- PR merge metrics
- PR metrics pending
Description
## Bug Report
Please answer these questions before submitting your issue. Thanks!
### 1. Minimal reproduce step (Required)
1. Create a materialized view and keep running a workload that continuously changes its base table, so the corresponding MLOG table receives inserts/updates.
2. Keep refreshing the materialized view so that MLOG purge jobs remove consumed MLOG rows.
3. Let MLOG auto analyze run for the MLOG table. In the observed run, the auto analyze job finished successfully and processed 437,962 rows on 2026-07-01.
4. Continue the same refresh/purge workload for a while.
5. Compare the MLOG table's physical row count with `mysql.stats_meta.count`, and check the MLOG purge history:
```sql
SELECT modify_count, count
FROM mysql.stats_meta
WHERE table_id = ;
SELECT COUNT(*) FROM .;
SELECT COUNT(*), SUM(PURGE_ROWS)
FROM mysql.tidb_mlog_purge_hist
WHERE MLOG_TABLE_ID =
AND START_TIME >
AND STATE = 'succeed';
```
Observed data from one validation run:
Immediately after the MLOG auto analyze job finished:
```text
mysql.stats_meta.modify_count = 303,320
mysql.stats_meta.count = 536,882
actual MLOG COUNT(*) = 399,882
```
After the workload kept running with refresh and purge:
```text
mysql.stats_meta.modify_count = 271,116,230
mysql.stats_meta.count = 44,206,320
actual MLOG COUNT(*) = 229,120
```
During the same window after the analyze job:
```text
successful MLOG purge jobs = 471
sum(PURGE_ROWS) = 113,477,695
successful refresh jobs = 480
sum(REFRESH_ROWS) = 125,224,301
```
In the same observation, `mysql.stats_histograms.version` for the MLOG table stayed at `2026-06-30 06:09:51.857`, even though `mysql.analyze_jobs` had a finished MLOG analyze job on 2026-07-01.
### 2. What did you expect to see? (Required)
After MLOG purge removes consumed rows, the MLOG table statistics should reflect the net row count instead of growing with historical MLOG insert volume.
After an MLOG analyze job finishes, subsequent refresh/purge cycles should not make `mysql.stats_meta.count` drift far away from the physical MLOG row count again. Otherwise the auto analyze trigger ratio and optimizer estimates for MLOG queries can be based on a greatly inflated row count.
If a finished analyze job is expected to rebuild stats for the MLOG table, `mysql.stats_histograms.version` should also be updated to the analyze time.
### 3. What did you see instead (Required)
`mysql.stats_meta.count` was corrected closer to the physical MLOG row count immediately after auto analyze, but then drifted upward again after refresh/purge continued.
In the observed run, the physical MLOG table had only 229,120 rows, while `mysql.stats_meta.count` reported 44,206,320 rows. This is about 193x larger than the real row count.
The workload had many successful MLOG purge jobs in the same window, so this looks like purge delete deltas are still not fully reflected in `mysql.stats_meta.count`, or are later overwritten by another MLOG stats update path.
`mysql.stats_histograms.version` also did not move to the finished analyze time in this observation.
### 4. What is your TiDB version? (Required)
```text
Release Version: v8.5.4-20260701-190c9d5
Edition: Enterprise
Git Commit Hash: 190c9d508e3ac309d45e13f12702cad959a00872
Git Branch: HEAD
UTC Build Time: 2026-07-01 08:09:19
GoVersion: go1.23.12
Race Enabled: false
Check Table Before Drop: false
Store: tikv
Enterprise Extension Commit Hash: 7d43ff65ebc145bd63fa84cb368f8775be906998
```
Contributor guide
Research direction
Start with the MLOG refresh, purge, and analyze paths that update mysql.stats_meta and mysql.stats_histograms; the report names no source files or tests, so trace these paths from the SQL reproduction and the listed system tables. Done means stats_meta.count remains close to the physical MLOG row count after refresh/purge cycles and the histogram version reflects a completed analyze job.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, sql
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100