Skip to content

Commit e207a44

Browse files
authored
VDiff: Save lastpk value for source and target (#17493)
Signed-off-by: Matt Lord <mattalord@gmail.com>
1 parent b0a5d66 commit e207a44

File tree

17 files changed

+1690
-736
lines changed

17 files changed

+1690
-736
lines changed

go/test/endtoend/vreplication/config_test.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,18 @@ import (
4545
// default collation as it has to work across versions and the 8.0 default does not exist in 5.7.
4646
var (
4747
// All standard user tables should have a primary key and at least one secondary key.
48-
customerTypes = []string{"'individual'", "'soho'", "'enterprise'"}
48+
customerTypes = []string{"'individual'", "'soho'", "'enterprise'"}
49+
customerTableTemplate = `create table customer(cid int auto_increment, name varchar(128) collate utf8mb4_bin, meta json default null,
50+
industryCategory varchar(100) generated always as (json_extract(meta, _utf8mb4'$.industry')) virtual, typ enum(%s),
51+
sport set('football','cricket','baseball'), ts timestamp not null default current_timestamp, bits bit(2) default b'11', date1 datetime not null default '0000-00-00 00:00:00',
52+
date2 datetime not null default '2021-00-01 00:00:00', dec80 decimal(8,0), blb blob, primary key(%s), key(name)) CHARSET=utf8mb4`
53+
customerTable = fmt.Sprintf(customerTableTemplate, strings.Join(customerTypes, ","), "cid,typ" /* PK columns */)
54+
// customerTableModifiedPK has a PK on (cid) vs (cid,typ).
55+
customerTableModifiedPK = fmt.Sprintf(customerTableTemplate, strings.Join(customerTypes, ","), "cid" /* PK columns */)
56+
4957
initialProductSchema = fmt.Sprintf(`
5058
create table product(pid int, description varbinary(128), date1 datetime not null default '0000-00-00 00:00:00', date2 datetime not null default '2021-00-01 00:00:00', primary key(pid), key(date1,date2)) CHARSET=utf8mb4;
51-
create table customer(cid int auto_increment, name varchar(128) collate utf8mb4_bin, meta json default null, industryCategory varchar(100) generated always as (json_extract(meta, _utf8mb4'$.industry')) virtual,
52-
typ enum(%s), sport set('football','cricket','baseball'), ts timestamp not null default current_timestamp, bits bit(2) default b'11', date1 datetime not null default '0000-00-00 00:00:00',
53-
date2 datetime not null default '2021-00-01 00:00:00', dec80 decimal(8,0), blb blob, primary key(cid,typ), key(name)) CHARSET=utf8mb4;
59+
%s;
5460
create table customer_seq(id int, next_id bigint, cache bigint, primary key(id)) comment 'vitess_sequence';
5561
create table merchant(mname varchar(128), category varchar(128), primary key(mname), key(category)) CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
5662
create table orders(oid int, cid int, pid int, mname varchar(128), price int, qty int, total int as (qty * price), total2 int as (qty * price) stored, primary key(oid), key(pid), key(cid)) CHARSET=utf8;
@@ -69,7 +75,8 @@ create table `+"`blüb_tbl`"+` (id int, val1 varchar(20), `+"`blöb1`"+` blob,
6975
create table reftable (id int, val1 varchar(20), primary key(id), key(val1));
7076
create table loadtest (id int, name varchar(256), primary key(id), key(name));
7177
create table nopk (name varchar(128), age int unsigned);
72-
`, strings.Join(customerTypes, ","))
78+
`, customerTable)
79+
7380
// These should always be ignored in vreplication
7481
internalSchema = `
7582
create table _1e275eef_3b20_11eb_a38f_04ed332e05c2_20201210204529_gho(id int, val varbinary(128), primary key(id));

go/test/endtoend/vreplication/multi_tenant_test.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,15 @@ type multiTenantMigration struct {
9191
}
9292

9393
const (
94-
mtSchema = "create table t1(id int, tenant_id int, primary key(id, tenant_id)) Engine=InnoDB"
94+
// The source/mt schema does not have the tenant_id column in the PK as adding a
95+
// column to a table can be done as an INSTANT operation whereas modifying a table's
96+
// PK requires a full table rebuild. So as a practical matter in production the
97+
// source schema will likely have the tenant_id column, but NOT have it be part of
98+
// the PK.
99+
mtSchema = "create table t1(id int, tenant_id int, primary key(id)) Engine=InnoDB"
100+
// The target/st schema must have the tenant_id column in the PK and the primary
101+
// vindex.
102+
stSchema = "create table t1(id int, tenant_id int, primary key(id, tenant_id)) Engine=InnoDB"
95103
mtVSchema = `
96104
{
97105
"multi_tenant_spec": {
@@ -127,7 +135,6 @@ const (
127135
}
128136
}
129137
`
130-
stSchema = mtSchema
131138
stVSchema = `
132139
{
133140
"tables": {
@@ -429,8 +436,11 @@ func (mtm *multiTenantMigration) insertSomeData(t *testing.T, tenantId int64, ke
429436
defer closeConn()
430437
idx := mtm.getLastID(tenantId)
431438
for i := idx + 1; i <= idx+numRows; i++ {
439+
// The source table has a PK on id only, so we have to make the id value
440+
// unique rather than relying on the combination of (id, tenant_id) for
441+
// our uniqueness.
432442
execQueryWithRetry(t, vtgateConn,
433-
fmt.Sprintf("insert into %s.t1(id, tenant_id) values(%d, %d)", keyspace, i, tenantId), queryTimeout)
443+
fmt.Sprintf("insert into %s.t1(id, tenant_id) values(%d, %d)", keyspace, i+(tenantId*1e4), tenantId), queryTimeout)
434444
}
435445
mtm.setLastID(tenantId, idx+numRows)
436446
}

go/test/endtoend/vreplication/vdiff2_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,15 @@ func TestVDiff2(t *testing.T) {
175175
require.NoError(t, err)
176176
verifyClusterHealth(t, vc)
177177

178+
// Pre-create the customer table on the target keyspace, with the primary key on
179+
// (cid) vs (cid,typ) on the source. This confirms that we are able to properly
180+
// diff the table when the source and target have a different PK definition.
181+
// Remove the 0 date restrictions as the customer table uses them in its DEFAULTs.
182+
execVtgateQuery(t, vtgateConn, targetKs, "set @@session.sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'")
183+
execVtgateQuery(t, vtgateConn, targetKs, customerTableModifiedPK)
184+
// Set the sql_mode back to the default.
185+
execVtgateQuery(t, vtgateConn, targetKs, "set @@session.sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'")
186+
178187
for _, tc := range testCases {
179188
t.Run(tc.name, func(t *testing.T) {
180189
// Primary tablets for any new shards are added in the first cell.

0 commit comments

Comments
 (0)