[DDL] FLASHBACK DATABASE can reset recovered sequence values and reuse existing IDs
- Dominant language
- Go
- Stars
- 40.5k
- Forks
- 6.2k
- PR merge metrics
- PR metrics pending
Description
# FLASHBACK DATABASE can reset recovered sequence values and reuse existing IDs
## Bug Report
### 1. Minimal reproduce step (Required)
The following reproduces the issue without failpoints:
```sql
DROP DATABASE IF EXISTS ai_native_seq_fb;
CREATE DATABASE ai_native_seq_fb;
USE ai_native_seq_fb;
CREATE SEQUENCE seq START WITH 1 INCREMENT BY 1 CACHE 100;
CREATE TABLE t (
id BIGINT PRIMARY KEY DEFAULT NEXT VALUE FOR seq,
note VARCHAR(64)
);
INSERT INTO t(note) VALUES ('before_1'), ('before_2');
SELECT * FROM t ORDER BY id;
SELECT NEXTVAL(seq) AS before_drop_nextval;
DROP DATABASE ai_native_seq_fb;
FLASHBACK DATABASE ai_native_seq_fb;
USE ai_native_seq_fb;
SELECT * FROM t ORDER BY id;
SELECT NEXTVAL(seq) AS after_flashback_nextval;
INSERT INTO t(note) VALUES ('after_flashback_default_insert');
```
Observed result:
```text
rows before DROP DATABASE: (1, before_1), (2, before_2)
before_drop_nextval: 3
rows after FLASHBACK DATABASE: (1, before_1), (2, before_2)
after_flashback_nextval: 1
following default INSERT: ERROR 1062 Duplicate entry '2' for key 't.PRIMARY'
```
The sequence object is present after recovery, but its allocation state has moved behind values
that already exist in the recovered table.
### 2. What did you expect to see? (Required)
`FLASHBACK DATABASE` should restore enough sequence state that a recovered sequence cannot allocate
values already materialized before the database was dropped. The post-recovery `NEXTVAL(seq)`
should continue beyond the recovered sequence state, and the following sequence-backed default
insert should succeed without a duplicate key.
### 3. What did you see instead (Required)
`FLASHBACK DATABASE` restores the sequence metadata and the table rows, but the sequence runtime
value is reset. `NEXTVAL(seq)` returns 1 even though IDs 1 and 2 already exist. The next default
insert then allocates 2 and fails with `ERROR 1062`.
This is behavioral state loss rather than only a `SHOW CREATE SEQUENCE` metadata difference. An
application using the recovered sequence as an identifier generator observes the generator moving
backward and reusing existing IDs.
### 4. Controls
The following controls were run on the same build:
- The same sequence and default-column path without database recovery produces IDs 1 and 2,
`NEXTVAL(seq)=3`, and a following default insert succeeds with ID 4.
- An `AUTO_INCREMENT` table containing IDs 1 and 2 was recovered with `FLASHBACK DATABASE`; its
following default insert succeeded with a non-colliding ID (30001 on the testbed).
These controls isolate the failure to recovery of sequence-specific runtime state, rather than the
default expression or generic database recovery path.
### 5. What is your TiDB version? (Required)
Reproduced without failpoints on an authorized test cluster:
```text
Release Version: v9.0.0-beta.2.pre-1895-g5c9198e948
Git Commit Hash: 5c9198e9484db852b8477ce0014e0422ff9ec6a9
Server string: 8.0.11-TiDB-v9.0.0-beta.2.pre-1895-g5c9198e948
```
### Suspected root cause
The schema recovery path enumerates historical objects through `ListTables` and routes each
`TableInfo`, including sequences, through the generic `recoverTable` path.
`recoverTable` calls `CreateTableAndSetAutoID`, which restores ordinary row ID, auto-increment, and
auto-random state. Sequence allocation state is stored separately under sequence-specific value
and cycle keys, and normal sequence creation uses `CreateSequenceAndSetSeqValue`. The generic table
recovery path does not rebuild those sequence keys.
The missing proof obligation is:
```text
recovering the historical TableInfo
does not imply
recovering all runtime state required by that object kind
```
A recovery test should verify post-recovery allocation behavior, not only that the sequence object
exists: `NEXTVAL` must not reuse existing values, and a sequence-backed default insert must remain
valid.
Found by AI-assisted testing.
Contributor guide
Research direction
Start by reading the ListTables and recoverTable recovery paths, then compare them with CreateSequenceAndSetSeqValue and the sequence-specific value and cycle keys. Run the provided FLASHBACK DATABASE reproduction and add recovery coverage showing that NEXTVAL advances beyond recovered IDs and a sequence-backed default insert avoids duplicate keys.
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
- 55/100