Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ddl: add restore deleted table #7937

Merged
merged 64 commits into from
Jan 16, 2019
Merged

Conversation

crazycs520
Copy link
Contributor

@crazycs520 crazycs520 commented Oct 17, 2018

What problem does this PR solve?

Add admin restore table by job job_id to restore the deleted table.
related proposal: #7383
related parser PR: pingcap/parser#85, pingcap/parser#172

What is changed ?

Add a new ddl type job: restore table to do restore.
the function of restore table almost as same as create table ddl.
But still a little bit different:

  • restore table don't do split table region.
  • restore table will rebase the table auto id with the original table autoID.

restore table usage

Scenario 1

If you drop table by mistake, you can use admin restore table [table_name] to restore the table.

Eg:

mysql> use test
You are now connected to database "test" as user "root"
mysql> create table t (a int)
mysql> insert into t values (1);
mysql> select a from t;
+---+
| a |
+---+
| 1 |
+---+
mysql> drop table t;
mysql> select a from t;
(1146, u"Table 'test.t' doesn't exist")
mysql> admin restore table test.t;
mysql> select a from t;
+---+
| a |
+---+
| 1 |
+---+
mysql> insert into t values (2);
mysql> select a from t;
+---+
| a |
+---+
| 1 |
| 2 |
+---+

Scenario 2

If you drop table t by mistable, then create a new table t, then drop the new table t, now, if you use admin restore table t, It will restore the new table t, not the ole table t . But how to restore the old table t ? You can use admin restore table by job [drop_table_job_ID] .

Eg:

mysql> use test
You are now connected to database "test" as user "root"
mysql> select * from t;
+---+
| a |
+---+
| 1 |
+---+
mysql> drop table t;
mysql> create table t (a int,b varchar(10));
mysql> insert into t values (1,"new t");
mysql> select * from t;
+---+-------+
| a | b     |
+---+-------+
| 1 | new t |
+---+-------+
mysql> drop table t;
mysql> admin restore table test.t;
mysql> select * from t;
+---+-------+
| a | b     |
+---+-------+
| 1 | new t |
+---+-------+
mysql> admin show ddl jobs;
+--------+---------+------------+---------------+--------------+-----------+----------+-----------+-----------------------------------+--------+
| JOB_ID | DB_NAME | TABLE_NAME | JOB_TYPE      | SCHEMA_STATE | SCHEMA_ID | TABLE_ID | ROW_COUNT | START_TIME                        | STATE  |
+--------+---------+------------+---------------+--------------+-----------+----------+-----------+-----------------------------------+--------+
| 73     | test    | t          | restore table | public       | 1         | 70       | 0         | 2019-01-13 14:55:59.016 +0800 CST | synced |
| 72     | test    | t          | drop table    | none         | 1         | 70       | 0         | 2019-01-13 14:55:54.116 +0800 CST | synced |
| 71     | test    | t          | create table  | public       | 1         | 70       | 0         | 2019-01-13 14:55:17.414 +0800 CST | synced |
| 69     | test    |            | drop table    | none         | 1         | 60       | 0         | 2019-01-13 14:55:03.262 +0800 CST | synced |
| 68     | test    |            | add index     | public       | 1         | 60       | 0         | 2019-01-13 14:54:28.415 +0800 CST | synced |
| 67     | test    |            | add index     | public       | 1         | 60       | 0         | 2019-01-13 14:54:24.563 +0800 CST | synced |
| 66     | test    |            | add index     | public       | 1         | 60       | 0         | 2019-01-13 14:54:20.611 +0800 CST | synced |
| 65     | test    |            | add index     | public       | 1         | 60       | 0         | 2019-01-13 14:54:10.915 +0800 CST | synced |
| 64     | test    |            | add index     | public       | 1         | 60       | 0         | 2019-01-13 14:54:05.511 +0800 CST | synced |
| 63     | test    |            | add index     | public       | 1         | 60       | 0         | 2019-01-13 14:54:01.411 +0800 CST | synced |
+--------+---------+------------+---------------+--------------+-----------+----------+-----------+-----------------------------------+--------+
10 rows in set
mysql> admin restore table by job 69; /* if you not sure which job drop the old table, you can also find this in tidb log file. */
(1050, u"Table 't' already exists")  /* because there is already have a table name `t`, so have to rename the table first. */
mysql> rename table t to t_new;
mysql> admin restore table by job 69;
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| t              |
| t_new          |
+----------------+
mysql> select * from t;
+---+
| a |
+---+
| 1 |
+---+
mysql> select * from t_new;
+---+-------+
| a | b     |
+---+-------+
| 1 | new t |
+---+-------+

Watch out

If you drop table t multiple time, then use admin recover table by job [ID] with the old drop job ID, there will have some problem when you write.

Eg:

mysql> use test
You are now connected to database "test" as user "root"
mysql> insert into t set b=1;
mysql> select * from t;
+---+---+
| a | b |
+---+---+
| 1 | 1 |
+---+---+
mysql> drop table t;
mysql> admin restore table t;
mysql> insert into t set b=2;
mysql> select * from t;
+-------+---+
| a     | b |
+-------+---+
| 1     | 1 |
| 30001 | 2 |
+-------+---+
mysql> drop table t;
mysql> admin show ddl jobs;
+--------+---------+------------+---------------+--------------+-----------+----------+-----------+-----------------------------------+--------+
| JOB_ID | DB_NAME | TABLE_NAME | JOB_TYPE      | SCHEMA_STATE | SCHEMA_ID | TABLE_ID | ROW_COUNT | START_TIME                        | STATE  |
+--------+---------+------------+---------------+--------------+-----------+----------+-----------+-----------------------------------+--------+
| 106    | test    |            | drop table    | none         | 1         | 94       | 0         | 2019-01-13 15:21:27.016 +0800 CST | synced |
| 105    | test    |            | restore table | public       | 1         | 94       | 0         | 2019-01-13 15:19:37.564 +0800 CST | synced |
| 104    | test    |            | drop table    | none         | 1         | 94       | 0         | 2019-01-13 15:19:29.318 +0800 CST | synced |
| 103    | test    |            | drop index    | none         | 1         | 94       | 0         | 2019-01-13 15:18:56.266 +0800 CST | synced |
| 102    | test    |            | drop index    | none         | 1         | 94       | 0         | 2019-01-13 15:18:50.815 +0800 CST | synced |
| 101    | test    |            | drop index    | none         | 1         | 94       | 0         | 2019-01-13 15:18:47.715 +0800 CST | synced |
| 100    | test    |            | drop index    | none         | 1         | 94       | 0         | 2019-01-13 15:18:45.364 +0800 CST | synced |
| 99     | test    |            | add index     | public       | 1         | 94       | 0         | 2019-01-13 15:18:25.263 +0800 CST | synced |
| 98     | test    |            | add index     | public       | 1         | 94       | 0         | 2019-01-13 15:18:22.063 +0800 CST | synced |
| 97     | test    |            | add index     | public       | 1         | 94       | 0         | 2019-01-13 15:18:10.763 +0800 CST | synced |
+--------+---------+------------+---------------+--------------+-----------+----------+-----------+-----------------------------------+--------+
mysql> admin restore table by job 104;
mysql> select * from t;
+-------+---+
| a     | b |
+-------+---+
| 1     | 1 |
| 30001 | 2 |
+-------+---+
mysql> insert into t set b=3;
mysql> select * from t;
+-------+---+
| a     | b |
+-------+---+
| 1     | 1 |
| 30001 | 3 |  /* Watch out: miss record b=2, This because record b=2 is covered by record b=3.*/
+-------+---+

summary

Normally recommend use admin restore table [table_name] to restore table. admin restore table by job [ID] is only for the Scenario 2.

How it works ?

This is done through the following steps:

  1. Get the history ddl job by job_id.
  2. Use the drop table job's StartTS to get a snapshot infoSchema before drop table.
  3. Find the table meta by table_id in snapshot infoSchema, if not found, return ErrTableIDNotExists.
  4. Using the Found table meta to create table( recover table ). the table_id is still the original table id. Return if encounter any error.
  5. Remove dropped table DDL job from gc_delete_range table by drop table job's id and table_id.

But Change Settings and undo Settings will make the problem more complicated.

Check List

Tests

  • Unit test
  • Manual test

Code changes

  • Has exported function/method change
  • Has exported variable/fields change
  • Has interface methods change

Side effects

  • Increased code complexity

Related changes


This change is Reviewable

@crazycs520
Copy link
Contributor Author

@winkyao @zimulala @ciscoxll PTAL.

@crazycs520
Copy link
Contributor Author

/run-all-tests

@crazycs520
Copy link
Contributor Author

/run-unit-test

@crazycs520
Copy link
Contributor Author

@zimulala @winkyao @ciscoxll PTAL

@crazycs520 crazycs520 changed the title ddl: add recover deleted table ddl: add restore deleted table Dec 15, 2018
@zyguan
Copy link
Contributor

zyguan commented Dec 15, 2018

Hi, @crazycs520 , ActionRestoreTable is undefined. you may need to bump parser first.

@zhouqiang-cl
Copy link
Contributor

/rebuild

@crazycs520 crazycs520 force-pushed the recover-table branch 2 times, most recently from 61e8680 to bb4f1ed Compare December 18, 2018 13:18
@crazycs520
Copy link
Contributor Author

db_partition_test

@crazycs520
Copy link
Contributor Author

/run-all-tests

@crazycs520
Copy link
Contributor Author

/run-all-tests

@ciscoxll
Copy link
Contributor

LGTM.

@ciscoxll ciscoxll added the status/LGT2 Indicates that a PR has LGTM 2. label Jan 15, 2019
@crazycs520
Copy link
Contributor Author

/run-all-tests

1 similar comment
@crazycs520
Copy link
Contributor Author

/run-all-tests

util/gcutil/gcutil.go Show resolved Hide resolved
executor/ddl.go Show resolved Hide resolved
executor/ddl.go Show resolved Hide resolved
executor/ddl.go Show resolved Hide resolved
ddl/table.go Show resolved Hide resolved
ddl/table.go Show resolved Hide resolved
ddl/table.go Show resolved Hide resolved
ddl/delete_range.go Outdated Show resolved Hide resolved
ddl/delete_range.go Outdated Show resolved Hide resolved
ddl/ddl_api.go Show resolved Hide resolved
domain/domain.go Outdated Show resolved Hide resolved
meta/meta.go Show resolved Hide resolved
executor/ddl_test.go Show resolved Hide resolved
ddl/serial_test.go Outdated Show resolved Hide resolved
ddl/serial_test.go Show resolved Hide resolved
@crazycs520
Copy link
Contributor Author

@zimulala PTAL again.

@crazycs520
Copy link
Contributor Author

/run-all-tests

@crazycs520
Copy link
Contributor Author

/run-unit-test

Copy link
Contributor

@zimulala zimulala left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to consider ServerStatusInTrans like other DDLs?

Copy link
Contributor

@zimulala zimulala left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@crazycs520
Copy link
Contributor Author

/run-all-tests

@crazycs520
Copy link
Contributor Author

/run-unit-test

@crazycs520 crazycs520 merged commit 365264c into pingcap:master Jan 16, 2019
@you06 you06 added the sig/sql-infra SIG: SQL Infra label Mar 4, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
sig/sql-infra SIG: SQL Infra status/LGT2 Indicates that a PR has LGTM 2.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants