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

Add default value when generate the update rows #1006

Merged
merged 11 commits into from
Nov 19, 2020
Merged

Conversation

july2993
Copy link
Contributor

@july2993 july2993 commented Nov 3, 2020

What problem does this PR solve?

What is changed and how it works?

only on the condition PreWrite.schemaVersion < schemaVersion of the
table replicated to downstream.

Check List

Tests

  • Manual test (add detailed scripts or steps below)

enable amend:
set global tidb_enable_amend_pessimistic_txn = 1;

run:

/* INIT */ drop table if exists t;
/* INIT */ create table t (id int primary key, c_str varchar(20));
/* INIT */ insert into t values (1, '0001'), (2, '0002'), (3, null), (4, '0003'), (5, null);
/* TXN */ begin;
/* TXN */ insert into t values (6, '0004');
/* TXN */ insert into t values (7, null);
/* DDL */ alter table t add c_str_new varchar(20);   # IN ANOTHER SESSION
/* TXN */ update t set c_str = '0005' where id = 1;
/* TXN */ update t set c_str = null where id = 2;
/* TXN */ update t set c_str = '0006' where id = 3;
/* TXN */ delete from t where id = 4;
/* TXN */ delete from t where id = 5;
/* TXN */ commit;
/* TXN */ select * from t order by id;
/* TXN */ admin check table t;

Code changes

Side effects

Release note

  • No Release note.

only on the condition PreWrite.schemaVersion < schemaVersion of the
table replicated to downstream.
@july2993
Copy link
Contributor Author

july2993 commented Nov 3, 2020

/run-all-tests tidb=release-4.0 tikv=release-4.0 pd=release-4.0

@you06
Copy link
Contributor

you06 commented Nov 3, 2020

Tested with this PR got unexpected NULL value in down stream

MySQL [test]> select * from accounts;                                                          │MySQL [test]> select * from accounts;
+----+---------+------+------+                                                                 │+----+---------+------+------+
| id | balance | aa   | bb   |                                                                 │| id | balance | aa   | bb   |
+----+---------+------+------+                                                                 │+----+---------+------+------+
|  1 |       1 |    1 |   10 |                                                                 │|  1 |       1 |    1 | NULL |
|  2 |       2 |    2 |   10 |                                                                 │|  2 |       2 |    2 | NULL |
|  3 |       3 |    3 |   10 |                                                                 │|  3 |       3 |    3 | NULL |
+----+---------+------+------+                                                                 │+----+---------+------+------+
3 rows in set (0.063 sec)                                                                      │3 rows in set (0.098 sec)
                                                                                               │
MySQL [test]> show create table accounts;                                                      │MySQL [test]> show create table accounts;
+----------+-----------------------------------------------------------------------------------│+----------+----------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------│----------------------------------------------------------------------------------------------
------------------------------------------------+                                              │--------------------------------------------------+
| Table    | Create Table                                                                      │| Table    | Create Table                                                                     
                                                                                               │                                                                                              
                                                |                                              │                                                  |
+----------+-----------------------------------------------------------------------------------│+----------+----------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------│----------------------------------------------------------------------------------------------
------------------------------------------------+                                              │--------------------------------------------------+
| accounts | CREATE TABLE `accounts` (                                                         │| accounts | CREATE TABLE `accounts` (
  `id` int(11) NOT NULL,                                                                       │  `id` int(11) NOT NULL,
  `balance` bigint(20) DEFAULT NULL,                                                           │  `balance` bigint(20) DEFAULT NULL,
  `aa` int(11) DEFAULT NULL,                                                                   │  `aa` int(11) DEFAULT NULL,
  `bb` int(11) DEFAULT 10,                                                                     │  `bb` int(11) DEFAULT 10,
  PRIMARY KEY (`id`)                                                                           │  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin |                                  │) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin |
+----------+-----------------------------------------------------------------------------------│+----------+----------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------│----------------------------------------------------------------------------------------------
------------------------------------------------+                                              │--------------------------------------------------+
1 row in set (0.051 sec)                                                                       │1 row in set (0.124 sec)
                                                                                               │

@july2993
Copy link
Contributor Author

july2993 commented Nov 3, 2020

Tested with this PR got unexpected NULL value in down stream

MySQL [test]> select * from accounts;                                                          │MySQL [test]> select * from accounts;
+----+---------+------+------+                                                                 │+----+---------+------+------+
| id | balance | aa   | bb   |                                                                 │| id | balance | aa   | bb   |
+----+---------+------+------+                                                                 │+----+---------+------+------+
|  1 |       1 |    1 |   10 |                                                                 │|  1 |       1 |    1 | NULL |
|  2 |       2 |    2 |   10 |                                                                 │|  2 |       2 |    2 | NULL |
|  3 |       3 |    3 |   10 |                                                                 │|  3 |       3 |    3 | NULL |
+----+---------+------+------+                                                                 │+----+---------+------+------+
3 rows in set (0.063 sec)                                                                      │3 rows in set (0.098 sec)
                                                                                               │
MySQL [test]> show create table accounts;                                                      │MySQL [test]> show create table accounts;
+----------+-----------------------------------------------------------------------------------│+----------+----------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------│----------------------------------------------------------------------------------------------
------------------------------------------------+                                              │--------------------------------------------------+
| Table    | Create Table                                                                      │| Table    | Create Table                                                                     
                                                                                               │                                                                                              
                                                |                                              │                                                  |
+----------+-----------------------------------------------------------------------------------│+----------+----------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------│----------------------------------------------------------------------------------------------
------------------------------------------------+                                              │--------------------------------------------------+
| accounts | CREATE TABLE `accounts` (                                                         │| accounts | CREATE TABLE `accounts` (
  `id` int(11) NOT NULL,                                                                       │  `id` int(11) NOT NULL,
  `balance` bigint(20) DEFAULT NULL,                                                           │  `balance` bigint(20) DEFAULT NULL,
  `aa` int(11) DEFAULT NULL,                                                                   │  `aa` int(11) DEFAULT NULL,
  `bb` int(11) DEFAULT 10,                                                                     │  `bb` int(11) DEFAULT 10,
  PRIMARY KEY (`id`)                                                                           │  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin |                                  │) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin |
+----------+-----------------------------------------------------------------------------------│+----------+----------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------│----------------------------------------------------------------------------------------------
------------------------------------------------+                                              │--------------------------------------------------+
1 row in set (0.051 sec)                                                                       │1 row in set (0.124 sec)
                                                                                               │

can you describe the detailed step?

@you06
Copy link
Contributor

you06 commented Nov 3, 2020

@july2993 I ran the following SQLs from upstream

/* init */ drop table if exists accounts;
/* init */ create table accounts(id int primary key, balance bigint, aa int);
/* init */ insert into accounts values(1, 100, 1), (2, 0, 2), (3, 1, 3);

/* TXN1 */ set session tidb_enable_amend_pessimistic_txn = 1;
/* DDL */ set session tidb_enable_amend_pessimistic_txn = 1;
/* TXN1 */ begin;
/* DDL */ alter table accounts add column bb int default 10;
/* TXN1 */ update accounts set balance = id where 1;
/* TXN1 */ commit;
/* TXN1 */ select * from accounts;

Copy link
Contributor

@lichunzhu lichunzhu left a comment

Choose a reason for hiding this comment

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

Should we add an integration test for this case?

@you06
Copy link
Contributor

you06 commented Nov 3, 2020

Tested with this PR got unexpected NULL value in down stream

MySQL [test]> select * from accounts;                                                          │MySQL [test]> select * from accounts;
+----+---------+------+------+                                                                 │+----+---------+------+------+
| id | balance | aa   | bb   |                                                                 │| id | balance | aa   | bb   |
+----+---------+------+------+                                                                 │+----+---------+------+------+
|  1 |       1 |    1 |   10 |                                                                 │|  1 |       1 |    1 | NULL |
|  2 |       2 |    2 |   10 |                                                                 │|  2 |       2 |    2 | NULL |
|  3 |       3 |    3 |   10 |                                                                 │|  3 |       3 |    3 | NULL |
+----+---------+------+------+                                                                 │+----+---------+------+------+
3 rows in set (0.063 sec)                                                                      │3 rows in set (0.098 sec)
                                                                                               │
MySQL [test]> show create table accounts;                                                      │MySQL [test]> show create table accounts;
+----------+-----------------------------------------------------------------------------------│+----------+----------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------│----------------------------------------------------------------------------------------------
------------------------------------------------+                                              │--------------------------------------------------+
| Table    | Create Table                                                                      │| Table    | Create Table                                                                     
                                                                                               │                                                                                              
                                                |                                              │                                                  |
+----------+-----------------------------------------------------------------------------------│+----------+----------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------│----------------------------------------------------------------------------------------------
------------------------------------------------+                                              │--------------------------------------------------+
| accounts | CREATE TABLE `accounts` (                                                         │| accounts | CREATE TABLE `accounts` (
  `id` int(11) NOT NULL,                                                                       │  `id` int(11) NOT NULL,
  `balance` bigint(20) DEFAULT NULL,                                                           │  `balance` bigint(20) DEFAULT NULL,
  `aa` int(11) DEFAULT NULL,                                                                   │  `aa` int(11) DEFAULT NULL,
  `bb` int(11) DEFAULT 10,                                                                     │  `bb` int(11) DEFAULT 10,
  PRIMARY KEY (`id`)                                                                           │  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin |                                  │) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin |
+----------+-----------------------------------------------------------------------------------│+----------+----------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------│----------------------------------------------------------------------------------------------
------------------------------------------------+                                              │--------------------------------------------------+
1 row in set (0.051 sec)                                                                       │1 row in set (0.124 sec)
                                                                                               │

It's caused by getDefaultOrZeroValue function will not populate default value column.

@july2993
Copy link
Contributor Author

july2993 commented Nov 4, 2020

/run-all-tests tidb=release-4.0 tikv=release-4.0 pd=release-4.0

@july2993
Copy link
Contributor Author

july2993 commented Nov 4, 2020

/run-all-tests tidb=release-4.0 tikv=release-4.0 pd=release-4.0

@july2993
Copy link
Contributor Author

july2993 commented Nov 4, 2020

/run-all-tests tidb=release-4.0 tikv=release-4.0 pd=release-4.0

@july2993
Copy link
Contributor Author

july2993 commented Nov 4, 2020

Should we add an integration test for this case?

yes, current test using a temporal tool https://github.com/july2993/tk/blob/4465f27496e7c6d8c509e8fde75bfce070c8c4b3/cmd/amend/amend.go#L42
we can port it if this solution if fine

@july2993 july2993 requested a review from lichunzhu November 4, 2020 07:57
@you06
Copy link
Contributor

you06 commented Nov 4, 2020

I tried this case and got error

/* init */ drop table if exists accounts;
/* init */ create table accounts(id int primary key, balance bigint);
/* init */ insert into accounts values(1, 100), (2, 0), (3, 1);

/* TXN */ set session tidb_enable_amend_pessimistic_txn = 1;
/* DDL */ set session tidb_enable_amend_pessimistic_txn = 1;
/* TXN */ begin;
/* DDL */ alter table accounts add column bb int not null;
/* DDL */ alter table accounts add column cc int not null;
/* TXN */ update accounts set balance = id where 1;
/* TXN */ commit;
/* TXN */ select * from accounts;
[2020/11/04 08:08:34.838 +00:00] [ERROR] [executor.go:111] ["Exec fail, will rollback"] [query="REPLACE INTO `test`.`accounts`(`balance`,`bb`,`id`) VALUES(?,?,?)"] [args="[3,0,3]"] [error="Error 1364: Field 'cc' doesn't have a default value"]

@july2993
Copy link
Contributor Author

july2993 commented Nov 4, 2020

/run-all-tests tidb=release-4.0 tikv=release-4.0 pd=release-4.0

@july2993
Copy link
Contributor Author

/run-all-tests tidb=release-4.0 tikv=release-4.0 pd=release-4.0

Copy link
Member

@csuzhangxc csuzhangxc left a comment

Choose a reason for hiding this comment

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

LGTM

@csuzhangxc
Copy link
Member

@you06 PTAL again?

@you06
Copy link
Contributor

you06 commented Nov 11, 2020

I'm running some tests on the latest commit.

@zyguan
Copy link

zyguan commented Nov 14, 2020

I did some tests today, there is a problem with enum type. The test case is

/* init */ drop table if exists t;
/* init */ create table t (id int primary key, c int);
/* init */ insert into t (id, c) values (1, 1);

/* txn */ begin;
/* txn */ update t set c = 2 where id = 1;
/* ddl */ alter table t add column cc enum('a','b','c','d','e') default 'b';
/* txn */ commit;

Drainer will execute REPLACE INTO test.t(c, cc, id) VALUES(2,0,1) on downstream, which will be rejected with Error 1265: Data truncated for column 'cc' . Drainer retried the txn for several times and finally exit with error. That is, we got a wrong default value for this enum column (Datum.b is "b" but Datum.i is 0).

@july2993
Copy link
Contributor Author

I did some tests today, there is a problem with enum type. The test case is

/* init */ drop table if exists t;
/* init */ create table t (id int primary key, c int);
/* init */ insert into t (id, c) values (1, 1);

/* txn */ begin;
/* txn */ update t set c = 2 where id = 1;
/* ddl */ alter table t add column cc enum('a','b','c','d','e') default 'b';
/* txn */ commit;

Drainer will execute REPLACE INTO test.t(c, cc, id) VALUES(2,0,1) on downstream, which will be rejected with Error 1265: Data truncated for column 'cc' . Drainer retried the txn for several times and finally exit with error. That is, we got a wrong default value for this enum column (Datum.b is "b" but Datum.i is 0).

fix in 18393fe

IsDroppingColumn(id int64) bool
CanAppendDefaultValue(id int64, schemaVersion int64) bool
// IsDroppingColumn(id int64) bool
TableBySchemaVersion(version int64, tid int64) (info *model.TableInfo, ok bool)
Copy link
Contributor

Choose a reason for hiding this comment

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

The variable name here is a bit confusing.

  • id and tid are both table's id.
  • version and schemaVersion are both schema's version.
  • the order of id and version is not same.

@you06
Copy link
Contributor

you06 commented Nov 18, 2020

LGTM

@ti-srebot
Copy link

@you06, Thanks for your review. The bot only counts LGTMs from Reviewers and higher roles, but you're still welcome to leave your comments. See the corresponding SIG page for more information. Related SIG: migrate(slack).

@july2993
Copy link
Contributor Author

/run-all-tests tidb=release-4.0 tikv=release-4.0 pd=release-4.0

@july2993 july2993 requested review from csuzhangxc and removed request for lichunzhu November 18, 2020 14:00
Copy link
Member

@csuzhangxc csuzhangxc left a comment

Choose a reason for hiding this comment

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

LGTM

@july2993 july2993 merged commit 336b519 into pingcap:master Nov 19, 2020
@july2993 july2993 deleted the amend branch November 19, 2020 02:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants