From 4cc21ed78906904c92d0359d725b6b90dcb0f236 Mon Sep 17 00:00:00 2001 From: winkyao Date: Tue, 14 Aug 2018 11:38:36 +0800 Subject: [PATCH 1/4] design: add a proposal to support a command 'ADMIN RESTORE TABLE table_id' to speed up recover faulty dropped table. --- .../2018-08-10-restore-dropped-table.md | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 docs/design/2018-08-10-restore-dropped-table.md diff --git a/docs/design/2018-08-10-restore-dropped-table.md b/docs/design/2018-08-10-restore-dropped-table.md new file mode 100644 index 0000000000000..0443f01297b57 --- /dev/null +++ b/docs/design/2018-08-10-restore-dropped-table.md @@ -0,0 +1,46 @@ + +# Proposal: + +- Author(s): [winkyao](https://github.com/winkyao) +- Last updated: 2018-08-10 + +## Abstract + +The proposal proposes to support `ADMIN RESTORE TABLE table_id` command, to restore the table that is dropped by faulty operation. + +## Background + +At present, if we drop the table in production environment, and realize the operations is faulty immediately. Before we support the proposed command, we can only [Reading Data From History Versions](https://pingcap.com/docs/op-guide/history-read/) to rescue the disaster. But it needs to read all the data in the storage, it spend too much time for our purpose that just restore the dropped table. + +## Proposal + +We can add a new command `ADMIN RESTORE TABLE table_id` to just make the dropped table be public again. If the data is not deleted by GC worker, this command can work. So it is better to enlarge the gc life time with `update mysql.tidb set variable_value='30h' where variable_name='tikv_gc_life_time';`, before we executing the statement. And the table and the original table data can be restore in a few seconds, it is a lot faster than before. It also can reduce the complexity of the operations, dissolves the artificial operation error. + +## Rationale + +Let's take a look what `DROP TABLE` statement does. `DROP TABLE` statement first remove the dropping table meta data from the coresponding database meta data. After the schemas are synced by all the TiDB instances, in `worker.deleteRange`, TiDB will insert a delete range that construct from the first row key to end row key of the dropping table into the table `mysql.gc_delete_range`. At most `max(gcDefaultRunInterval, gcLifeTimeKey)` time later, the GC worker will delete the table data finally. + +The meta data of the table is not really deleted, the meta key format is `Table:table_id`, as long as we can find out the id of the dropped table, we can recover the table information. The `admin show ddl jobs` statement can retrive the table id: + +``` ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------+ +| JOBS | STATE | ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------+ +| ID:44, Type:drop table, State:synced, SchemaState:none, SchemaID:1, TableID:39, RowCount:0, ArgLen:0, start time: 2018-08-11 11:23:53.308 +0800 CST, Err:, ErrCount:0, SnapshotVersion:0 | synced | ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------+ +``` + +As you can see, if we can restore the table before the GC worker delete the table data, we can restore the table completely, if the table data is deleted, we can only restore an empty table. + +## Compatibility + +It's a new command, will not lead to compatibility issues. + +## Implementation + +1. `ADMIN RESTORE TABLE table_id` will enqueue a new DDL job to TiDB general DDL queue. +2. Before we start to do this job, we need to check if the table name is already exists(created a new table with the same table name after you drop it), if it is exists, return `ErrTableExists` error. +3. Secondly, find out whether the delete-range of the dropped table is still in the `mysql.gc_delete_range`, if not, means that the GC worker is cleanup the data, we can not restore the table successfully, return a error to the client. If it is still there, we remove the record in the `mysql.gc_delete_range` table, if we successfully remove, continue to step 4, otherwise we return a error to the client to indicate the command can not execute safely. +4. Remove the delete-range record in the `mysql.gc_delete_range` table, to prevent GC worker deleting the real data. +5. Use the previous table meta infomation of the table_id to insert the meta data into the schema meta data, like what `Meta.CreateTable` does. And make the table infomation state to be `model.StatePublic`, then the restore is finished after the schema is synced by all the TiDB instances. +6. If the command is canceled or rollbacked, and the delete-range record is already removed, we need to insert it into the `mysql.gc_delete_range` again, like what `Drop Table` does in `worker.finishDDLJob`. From e0ec0d8c5c32d60ee650528650ad9f2f262b8c72 Mon Sep 17 00:00:00 2001 From: winkyao Date: Tue, 14 Aug 2018 21:18:42 +0800 Subject: [PATCH 2/4] address comment --- .../2018-08-10-restore-dropped-table.md | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/docs/design/2018-08-10-restore-dropped-table.md b/docs/design/2018-08-10-restore-dropped-table.md index 0443f01297b57..4f2ea16cb6f74 100644 --- a/docs/design/2018-08-10-restore-dropped-table.md +++ b/docs/design/2018-08-10-restore-dropped-table.md @@ -10,17 +10,17 @@ The proposal proposes to support `ADMIN RESTORE TABLE table_id` command, to rest ## Background -At present, if we drop the table in production environment, and realize the operations is faulty immediately. Before we support the proposed command, we can only [Reading Data From History Versions](https://pingcap.com/docs/op-guide/history-read/) to rescue the disaster. But it needs to read all the data in the storage, it spend too much time for our purpose that just restore the dropped table. +At present, if we drop the table in production environment, we will realize whether the operation is faulty immediately. Before we support the proposed command, we can only [reading data from history versions](https://pingcap.com/docs/op-guide/history-read/) to relieve the disaster. But it needs to read all the data in the storage and it takes too much time to just restore the dropped the table. ## Proposal -We can add a new command `ADMIN RESTORE TABLE table_id` to just make the dropped table be public again. If the data is not deleted by GC worker, this command can work. So it is better to enlarge the gc life time with `update mysql.tidb set variable_value='30h' where variable_name='tikv_gc_life_time';`, before we executing the statement. And the table and the original table data can be restore in a few seconds, it is a lot faster than before. It also can reduce the complexity of the operations, dissolves the artificial operation error. +We can add a new command `ADMIN RESTORE TABLE table_id` to just make the dropped table public again. If the data is not deleted by GC worker, this command can work. So it is better to enlarge the GC life time with `update mysql.tidb set variable_value='30h' where variable_name='tikv_gc_life_time';`, before we executing the statement. The table and the original table data can be restored in a few seconds and it is a lot faster than before. It also can reduce the complexity of the operations and dissolves the artificial operation error. ## Rationale -Let's take a look what `DROP TABLE` statement does. `DROP TABLE` statement first remove the dropping table meta data from the coresponding database meta data. After the schemas are synced by all the TiDB instances, in `worker.deleteRange`, TiDB will insert a delete range that construct from the first row key to end row key of the dropping table into the table `mysql.gc_delete_range`. At most `max(gcDefaultRunInterval, gcLifeTimeKey)` time later, the GC worker will delete the table data finally. +Let's take a look at the workflow of the `DROP TABLE` statement. The `DROP TABLE` statement first removes the dropping table meta data from the coresponding database meta data. After the schemas are synced by all the TiDB instances, in `worker.deleteRange`, TiDB will insert a deleted range of the first row key to the end row key of the dropping table into the table `mysql.gc_delete_range`. At most `max(gcDefaultRunInterval, gcLifeTimeKey)` time later, the GC worker will delete the table data finally. -The meta data of the table is not really deleted, the meta key format is `Table:table_id`, as long as we can find out the id of the dropped table, we can recover the table information. The `admin show ddl jobs` statement can retrive the table id: +The meta data of the table is not really deleted. The meta key format is `Table:table_id`. As long as we can find out the ID of the dropped table, we can recover the table information. The `admin show ddl jobs` statement can retrive the table ID: ``` +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------+ @@ -30,17 +30,20 @@ The meta data of the table is not really deleted, the meta key format is `Table: +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------+ ``` -As you can see, if we can restore the table before the GC worker delete the table data, we can restore the table completely, if the table data is deleted, we can only restore an empty table. +As you can see, if we can restore the table before the GC worker deletes the table data, we can restore the table completely. If the table data is deleted, we can only restore an empty table. + +Before we run the `ADMIN RESTORE TABLE table_id`, you must: +* Ensure that there is no any GC tasks is running, you can figure out this by using TiDB logs and metrics. +* Enlarge the `tikv_gc_life_time` to a sufficient value. ## Compatibility -It's a new command, will not lead to compatibility issues. +It's a new command and will not lead to compatibility issues. -## Implementation +## Implementatio 1. `ADMIN RESTORE TABLE table_id` will enqueue a new DDL job to TiDB general DDL queue. -2. Before we start to do this job, we need to check if the table name is already exists(created a new table with the same table name after you drop it), if it is exists, return `ErrTableExists` error. -3. Secondly, find out whether the delete-range of the dropped table is still in the `mysql.gc_delete_range`, if not, means that the GC worker is cleanup the data, we can not restore the table successfully, return a error to the client. If it is still there, we remove the record in the `mysql.gc_delete_range` table, if we successfully remove, continue to step 4, otherwise we return a error to the client to indicate the command can not execute safely. -4. Remove the delete-range record in the `mysql.gc_delete_range` table, to prevent GC worker deleting the real data. -5. Use the previous table meta infomation of the table_id to insert the meta data into the schema meta data, like what `Meta.CreateTable` does. And make the table infomation state to be `model.StatePublic`, then the restore is finished after the schema is synced by all the TiDB instances. -6. If the command is canceled or rollbacked, and the delete-range record is already removed, we need to insert it into the `mysql.gc_delete_range` again, like what `Drop Table` does in `worker.finishDDLJob`. +2. Before we start to do this job, we need to check if the table name is already exists(created a new table with the same table name after you drop it). If it exists, return `ErrTableExists` error. +3. Secondly, find out whether the delete-range of the dropped table is still in the `mysql.gc_delete_range`. If not, it means that the GC worker has cleanup the data. In this situation, we cannot restore the table successfully but return an error to the client. If it is still there, we remove the record in the `mysql.gc_delete_range` table. If we successfully remove the record, continue to step 4, otherwise we return an error to the client to indicate the command cannot execute safely. +4. Use the previous table meta infomation of the table_id to insert the meta data into the schema meta data, like what `Meta.CreateTable` does. And set the table information state to `model.StatePublic`, then the restoration will be finished after the schema is synced by all the TiDB instances. +5. If the command is canceled or rollbacked, and the delete-range record is already removed, we need to insert it into `mysql.gc_delete_range` again, like what `Drop Table` does in `worker.finishDDLJob`. From 44292dd000c8e26d6beaa82364420ca3f9fb9a9c Mon Sep 17 00:00:00 2001 From: winkyao Date: Tue, 14 Aug 2018 21:20:27 +0800 Subject: [PATCH 3/4] address comment --- docs/design/2018-08-10-restore-dropped-table.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/design/2018-08-10-restore-dropped-table.md b/docs/design/2018-08-10-restore-dropped-table.md index 4f2ea16cb6f74..62967deb703b9 100644 --- a/docs/design/2018-08-10-restore-dropped-table.md +++ b/docs/design/2018-08-10-restore-dropped-table.md @@ -6,7 +6,7 @@ ## Abstract -The proposal proposes to support `ADMIN RESTORE TABLE table_id` command, to restore the table that is dropped by faulty operation. +This proposal proposes to support the `ADMIN RESTORE TABLE table_id` command, to restore the table that is dropped by a faulty operation. ## Background From 303ce64b1dbcda835a1bdabc7a6551d385cfef4d Mon Sep 17 00:00:00 2001 From: winkyao Date: Wed, 15 Aug 2018 14:26:04 +0800 Subject: [PATCH 4/4] address comment --- .../2018-08-10-restore-dropped-table.md | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/design/2018-08-10-restore-dropped-table.md b/docs/design/2018-08-10-restore-dropped-table.md index 62967deb703b9..2210b565920fe 100644 --- a/docs/design/2018-08-10-restore-dropped-table.md +++ b/docs/design/2018-08-10-restore-dropped-table.md @@ -10,17 +10,17 @@ This proposal proposes to support the `ADMIN RESTORE TABLE table_id` command, to ## Background -At present, if we drop the table in production environment, we will realize whether the operation is faulty immediately. Before we support the proposed command, we can only [reading data from history versions](https://pingcap.com/docs/op-guide/history-read/) to relieve the disaster. But it needs to read all the data in the storage and it takes too much time to just restore the dropped the table. +At present, if we drop the table in production environment, we will realize whether the operation is faulty immediately. Before we support the proposed command, we can only [read data from history versions](https://pingcap.com/docs/op-guide/history-read/) to relieve the disaster. But it needs to read all the data in the storage and it takes too much time to just restore the dropped the table. ## Proposal -We can add a new command `ADMIN RESTORE TABLE table_id` to just make the dropped table public again. If the data is not deleted by GC worker, this command can work. So it is better to enlarge the GC life time with `update mysql.tidb set variable_value='30h' where variable_name='tikv_gc_life_time';`, before we executing the statement. The table and the original table data can be restored in a few seconds and it is a lot faster than before. It also can reduce the complexity of the operations and dissolves the artificial operation error. +We can add a new command `ADMIN RESTORE TABLE table_id` to just make the dropped table public again. If the data is not deleted by GC worker, this command can work. So it is better to enlarge the GC life time with `update mysql.tidb set variable_value='30h' where variable_name='tikv_gc_life_time';`, before we execute the statement. The table and the original table data can be restored in a few seconds and it is a lot faster than before. It also can reduce the complexity of the operations and dissolve the artificial operation error. ## Rationale Let's take a look at the workflow of the `DROP TABLE` statement. The `DROP TABLE` statement first removes the dropping table meta data from the coresponding database meta data. After the schemas are synced by all the TiDB instances, in `worker.deleteRange`, TiDB will insert a deleted range of the first row key to the end row key of the dropping table into the table `mysql.gc_delete_range`. At most `max(gcDefaultRunInterval, gcLifeTimeKey)` time later, the GC worker will delete the table data finally. -The meta data of the table is not really deleted. The meta key format is `Table:table_id`. As long as we can find out the ID of the dropped table, we can recover the table information. The `admin show ddl jobs` statement can retrive the table ID: +The meta data of the table is not really deleted. The meta key format is `Table:table_id`. As long as we can find out the ID of the dropped table, we can recover the table information. The `admin show ddl jobs` statement can retrieve the table ID: ``` +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------+ @@ -32,18 +32,18 @@ The meta data of the table is not really deleted. The meta key format is `Table: As you can see, if we can restore the table before the GC worker deletes the table data, we can restore the table completely. If the table data is deleted, we can only restore an empty table. -Before we run the `ADMIN RESTORE TABLE table_id`, you must: -* Ensure that there is no any GC tasks is running, you can figure out this by using TiDB logs and metrics. -* Enlarge the `tikv_gc_life_time` to a sufficient value. +Before we run `ADMIN RESTORE TABLE table_id`, you must: +* Ensure that no GC task is running and then you can figure this by using TiDB logs and metrics. +* Increase `tikv_gc_life_time` to a sufficient value. ## Compatibility It's a new command and will not lead to compatibility issues. -## Implementatio +## Implementation 1. `ADMIN RESTORE TABLE table_id` will enqueue a new DDL job to TiDB general DDL queue. -2. Before we start to do this job, we need to check if the table name is already exists(created a new table with the same table name after you drop it). If it exists, return `ErrTableExists` error. -3. Secondly, find out whether the delete-range of the dropped table is still in the `mysql.gc_delete_range`. If not, it means that the GC worker has cleanup the data. In this situation, we cannot restore the table successfully but return an error to the client. If it is still there, we remove the record in the `mysql.gc_delete_range` table. If we successfully remove the record, continue to step 4, otherwise we return an error to the client to indicate the command cannot execute safely. -4. Use the previous table meta infomation of the table_id to insert the meta data into the schema meta data, like what `Meta.CreateTable` does. And set the table information state to `model.StatePublic`, then the restoration will be finished after the schema is synced by all the TiDB instances. +2. Before we start to do this job, we need to check if the table name already exists (created a new table with the same table name after you drop it). If it exists, return the `ErrTableExists` error. +3. Find out whether the delete-range of the dropped table is still in `mysql.gc_delete_range`. If not, it means that the GC worker has cleaned up the data. In this situation, we cannot restore the table successfully but return an error to the client. If it is still there, we remove the record in the `mysql.gc_delete_range` table. If we successfully remove the record, continue to Step 4; otherwise, we return an error to the client to indicate the command cannot be executed safely. +4. Use the previous table meta information of the table_id to insert the meta data into the schema meta data, like what `Meta.CreateTable` does. And set the table information state to `model.StatePublic`, then the restoration will be finished after the schema is synced by all the TiDB instances. 5. If the command is canceled or rollbacked, and the delete-range record is already removed, we need to insert it into `mysql.gc_delete_range` again, like what `Drop Table` does in `worker.finishDDLJob`.