349 lines
11 KiB
Plaintext
349 lines
11 KiB
Plaintext
#
|
|
# Test for read before write removal(rbwr) optimization in MySQL Cluster
|
|
#
|
|
# Parameter based testcase using a table containing the different queries
|
|
# and their expected number of roundtrips(regarding rbwr). This allows the
|
|
# same queries to be run with different settings while making sure that
|
|
# the query result is always the same. Of course some settings causes the
|
|
# rbwr optimzation to not apply and the expected number of roundtrips etc.
|
|
# shouldn't be checked.
|
|
#
|
|
-- source include/have_ndb.inc
|
|
|
|
--disable_query_log
|
|
--disable_result_log
|
|
|
|
### Setup parameter tables and utility procedures
|
|
create table rbwr_tests (
|
|
test_id int primary key auto_increment,
|
|
table_name varchar(255),
|
|
query varchar(255),
|
|
execute_count int,
|
|
affected_rows int
|
|
) engine = MEMORY;
|
|
|
|
### Setup test tables
|
|
# Same table as ndb_update_no_read
|
|
create table t1 (
|
|
a int not null primary key,
|
|
b int not null,
|
|
c int,
|
|
unique index_b (b) using hash
|
|
) engine = ndb;
|
|
create temporary table data_t1 (
|
|
a int not null primary key,
|
|
b int not null,
|
|
c int
|
|
);
|
|
insert into data_t1 values
|
|
(1,10,1),(2,9,1),(3,8,1),(4,7,1),(5,6,1),
|
|
(6,5,2),(7,4,2),(8,3,2),(9,2,2),(10,1,2);
|
|
|
|
# Composite PK
|
|
create table t2 (
|
|
pk_a int not null,
|
|
pk_b int not null,
|
|
pk_c int not null,
|
|
PRIMARY KEY (pk_a,pk_b,pk_c),
|
|
d int
|
|
) engine = ndb;
|
|
create temporary table data_t2 (
|
|
a int not null,
|
|
b int not null,
|
|
c int not null,
|
|
d int
|
|
);
|
|
insert into data_t2 values
|
|
(1,10,1,37),(2,9,1,38),(3,8,1,39),(4,7,1,40),(5,6,1,41),
|
|
(6,5,2,42),(7,4,2,43),(8,3,2,44),(9,2,2,45),(10,1,2,46);
|
|
|
|
#
|
|
create table t3 (
|
|
pk_a varchar(256) not null,
|
|
b int not null,
|
|
c int not null,
|
|
PRIMARY KEY (pk_a),
|
|
unique index_cb (c,b) using hash,
|
|
d int
|
|
) engine = ndb;
|
|
create temporary table data_t3 (
|
|
a varchar(256) not null,
|
|
b int not null,
|
|
c int not null,
|
|
d int
|
|
);
|
|
insert into data_t3 values
|
|
('11111',10,1,44),('22222',9,2,45),('33333',8,3,46),('44444',7,4,47),('55555',6,5,48),
|
|
('66666',5,6,44),('77777',4,7,45),('88888',3,8,46),('99999',2,9,47),('00000',1,10,48);
|
|
|
|
# Composite PK, more rows, random number of rows
|
|
create table t4 (
|
|
pk_a varchar(256) not null,
|
|
pk_b int not null,
|
|
pk_c datetime not null,
|
|
PRIMARY KEY (pk_a, pk_b, pk_c),
|
|
d int,
|
|
e varchar(255),
|
|
f int,
|
|
unique index_f (f) using hash,
|
|
g bigint,
|
|
h bigint,
|
|
i bigint,
|
|
j bigint,
|
|
unique index_ghij (g,h,i,j) using hash
|
|
) engine = ndb;
|
|
create temporary table data_t4 (
|
|
a varchar(256) not null,
|
|
b int not null,
|
|
c datetime not null,
|
|
d int,
|
|
e varchar(255),
|
|
f int,
|
|
g bigint,
|
|
h int,
|
|
i bigint,
|
|
j char(11)
|
|
);
|
|
let $i = `select round(rand() * 10)`;
|
|
while ($i)
|
|
{
|
|
eval insert into data_t4 values (
|
|
REPEAT('$i', 4),
|
|
$i,
|
|
DATE_ADD("2012-10-15 11:11:11", INTERVAL $i SECOND),
|
|
100000-$i,
|
|
REPEAT(CHAR(64+25*RAND()), 1+254*RAND()),
|
|
$i,
|
|
1000+$i,
|
|
10000+$i,
|
|
100000+$i,
|
|
1000000+$i
|
|
);
|
|
|
|
dec $i;
|
|
}
|
|
|
|
#Table with BLOB
|
|
create table t5 (
|
|
a int not null primary key,
|
|
b int not null,
|
|
c int,
|
|
d text,
|
|
unique index_b (b) using hash
|
|
) engine = ndb;
|
|
create temporary table data_t5 (
|
|
a int not null primary key,
|
|
b int not null,
|
|
c int,
|
|
d text
|
|
);
|
|
insert into data_t5 values
|
|
(1,10,1,'aaa'),(2,9,1,'bbb'),(3,8,1,'ccc'),(4,7,1,''),(5,6,1,NULL),
|
|
(6,5,2,'foo'),(7,4,2,'xxx'),(8,3,2,'yyy'),(9,2,2,'zzz'),(10,1,3,'xyz');
|
|
|
|
#enable_result_log;
|
|
#select * from data_t4;
|
|
#exit;
|
|
|
|
|
|
### Add test cases and their expected execute_count results
|
|
|
|
# Same testcases as ndb_update_no_read
|
|
INSERT INTO rbwr_tests (table_name, query, execute_count) VALUES
|
|
("t1", "update t1 set c = 97, b = 98 where a = 1", 2),
|
|
("t1", "delete from t1 where a = 1", 1),
|
|
("t1", "update t1 set c = 97 where b = 2", 1),
|
|
("t1", "update t1 set c = 97, b = 98 where b = 2", 2),
|
|
("t1", "delete from t1 where b = 9", 1),
|
|
("t1", "update t1 set c = 97 where a = 10 or a >= 10", 3),
|
|
("t1", "update t1 set c = 97 where a in (8,10)", 1),
|
|
("t1", "update t1 set c = 97 where a in (7,8) or a >= 10", 4),
|
|
("t1", "update t1 set a = 99, b = 98 where a = 3", 4),
|
|
("t1", "update t1 set a = 99, b = 98 where b = 7", 4),
|
|
("t1", "update t1 set c = 97, b = 98 where a = 5 and b = 6", 2),
|
|
("t1", "delete from t1 where b = 8 and c = 2", 2);
|
|
|
|
# Using full primary key, one roundtrip
|
|
INSERT INTO rbwr_tests (table_name, query, execute_count) VALUES
|
|
("t1", "delete from t1 where a = 1", 1),
|
|
("t1", "update t1 set c = 37 where a = 1", 1),
|
|
("t2", "delete from t2 where pk_a = 1 and pk_b = 2 and pk_c = 3", 1),
|
|
("t2", "update t2 set d = 37 where pk_a = 1 and pk_b = 2 and pk_c = 3", 1),
|
|
("t3", "delete from t3 where pk_a = \"11111\"", 1),
|
|
("t3", "update t3 set d = 37 where pk_a = \"11111\"", 1),
|
|
("t4", "delete from t4 where pk_a = \"16161616\" and pk_b = 16
|
|
and pk_c = \"2012-10-15 11:11:27\"", 1),
|
|
("t4", "update t4 set d = 37 where pk_a = \"16161616\" and pk_b = 16
|
|
and pk_c = \"2012-10-15 11:11:27\"", 1);
|
|
|
|
# Using full unique key, one roundtrip
|
|
INSERT INTO rbwr_tests (table_name, query, execute_count) VALUES
|
|
("t1", "delete from t1 where b = 1", 1),
|
|
("t1", "update t1 set c = 37 where b = 1", 1),
|
|
# no unique key in t2
|
|
("t3", "delete from t3 where c = 2 and b = 9", 1),
|
|
("t3", "update t3 set d = 37 where c = 2 and b = 9", 1),
|
|
# The 4 cases below should supposedly also use only 1 roundtrip
|
|
("t4", "delete from t4 where f = 37", 2),
|
|
("t4", "update t4 set d = 37 where f = 37", 2),
|
|
("t4", "delete from t4
|
|
where g = 1009 and h = 10009 and i = 100009 and j = \"1000009\"", 2),
|
|
("t4", "update t4 set d = 37
|
|
where g = 1009 and h = 10009 and i = 100009 and j = \"1000009\"", 2);
|
|
|
|
# Update (part of) primary key (may require read+delete+insert+commit)
|
|
INSERT INTO rbwr_tests (table_name, query, execute_count) VALUES
|
|
# All columns in PK updated
|
|
("t1", "update t1 set a = 97 where a = 1", 4), #PK
|
|
("t1", "update t1 set a = 98 where b = 1", 4), #Unique key
|
|
|
|
# Update PK as keyop
|
|
("t2", "update t2 set pk_a = 37 where pk_a = 1 and pk_b = 2 and pk_c = 3", 2), #No match
|
|
("t2", "update t2 set pk_a = 38 where pk_a = 9 and pk_b = 2 and pk_c = 2", 4),
|
|
("t2", "update t2 set pk_b = 39 where pk_a = 9 and pk_b = 2 and pk_c = 2", 4),
|
|
|
|
# Update PK as index-rangeop
|
|
("t2", "update t2 set pk_a = 47 where pk_a = 1 and pk_b = 2", 2), #No match
|
|
("t2", "update t2 set pk_a = 48 where pk_a = 9 and pk_b = 2", 6),
|
|
|
|
# Update PK on table having BLOB
|
|
("t5", "update t5 set a = 57 where a = 1", 4), #PK
|
|
("t5", "update t5 set a = 58 where b = 1", 4), #Unique key
|
|
|
|
# Update PK on table having BLOB, non existing rows
|
|
("t5", "update t5 set a = 57 where a = 99", 2), #PK
|
|
("t5", "update t5 set a = 58 where b = 99", 2) #Unique key
|
|
;
|
|
|
|
# Update or delete of table with BLOB (Column 'd')
|
|
set @b1 = 'b1';
|
|
set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1);
|
|
set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1);
|
|
set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1);
|
|
|
|
INSERT INTO rbwr_tests (table_name, query, execute_count) VALUES
|
|
("t5", "update t5 set d = @b1 where a = 1", 3), #PK
|
|
("t5", "update t5 set d = NULL where a = 1", 3), #PK
|
|
|
|
("t5", "update t5 set d = @b1 where b = 1", 3), #UQ index
|
|
("t5", "update t5 set d = NULL where b = 1", 3), #UQ index
|
|
|
|
("t5", "update t5 set d = @b1 where c = 3", 3), #Scan 1 row
|
|
("t5", "update t5 set d = NULL where c = 3", 3), #Scan, update 1 row
|
|
#("t5", "update t5 set d = @b1 where c > 1", 7), #Scan, update 5 rows
|
|
#("t5", "update t5 set d = @b1", 12), #Scan, update 10 rows
|
|
|
|
# Update BLOB in non existing rows
|
|
("t5", "update t5 set d = @b1 where a = 99", 2), #PK
|
|
("t5", "update t5 set d = NULL where a = 99", 2), #PK
|
|
|
|
("t5", "update t5 set d = @b1 where b = 99", 2), #UQ index
|
|
("t5", "update t5 set d = NULL where b = 99", 2), #UQ index
|
|
|
|
("t5", "update t5 set d = @b1 where c = 99", 2), #Scan
|
|
("t5", "update t5 set d = NULL where c = 99", 2), #Scan
|
|
|
|
# Update BLOB also req. to read the BLOB column
|
|
("t5", "update t5 set d = concat(d,@b1) where a = 1", 3), #PK
|
|
("t5", "update t5 set d = concat(d,@b1) where b = 1", 3), #UQ index
|
|
("t5", "update t5 set d = concat(d,@b1) where c = 3", 3), #Scan 1 row
|
|
#("t5", "update t5 set d = concat(d,@b1) where c > 1", 7), #Scan 5 rows
|
|
#("t5", "update t5 set d = concat(d,@b1)", 11), #Scan 10 rows
|
|
|
|
# Delete rows with BLOB
|
|
("t5", "delete from t5 where a = 1", 2), #PK
|
|
("t5", "delete from t5 where b = 1", 2), #UQ index
|
|
("t5", "delete from t5 where c = 3", 3), #Scan, single match
|
|
#("t5", "delete from t5 where c > 1", 4), #Scan, match 5 rows
|
|
#("t5", "delete from t5 where c > 0", 4), #Scan, match 10 rows
|
|
("t5", "delete from t5 where c > 9", 2) #Scan, no match
|
|
#("t5", "delete from t5", 4)
|
|
;
|
|
|
|
|
|
### Run testcases while there are tests left in the param table
|
|
while (`select count(*) from rbwr_tests`)
|
|
{
|
|
# Find one testcase
|
|
select @test_id := test_id,
|
|
@test_table := table_name,
|
|
@test_query := query,
|
|
@test_execute_count := execute_count,
|
|
@test_affected_rows := affected_rows
|
|
from rbwr_tests order by test_id limit 1;
|
|
let $test_query = `select @test_query`;
|
|
let $test_table = `select @test_table`;
|
|
let $test_execute_count = `select @test_execute_count`;
|
|
|
|
--source ndb_rbwr.inc
|
|
|
|
# Delete testcase
|
|
delete from rbwr_tests where test_id = @test_id;
|
|
}
|
|
|
|
## Table with triggers
|
|
CREATE TABLE main(id int NOT NULL AUTO_INCREMENT PRIMARY KEY, val int)engine=ndb;
|
|
CREATE TABLE log(id int NOT NULL AUTO_INCREMENT PRIMARY KEY, bug_text varchar(500) NOT NULL)engine=ndb;
|
|
|
|
# Check execute count to verify that read removal is not done for
|
|
# a delete on a table which has a delete trigger
|
|
CREATE TRIGGER log_deletes AFTER DELETE ON main FOR EACH ROW
|
|
INSERT INTO log (bug_text) VALUES ("one row deleted");
|
|
|
|
let $before= `select VARIABLE_VALUE from performance_schema.session_status
|
|
where variable_name like 'NDB_EXECUTE_COUNT'`;
|
|
eval DELETE FROM main WHERE id = 1;
|
|
let $after= `select VARIABLE_VALUE from performance_schema.session_status
|
|
where variable_name like 'NDB_EXECUTE_COUNT'`;
|
|
if (!`select $after-$before >= 4`)
|
|
{
|
|
enable_result_log;
|
|
echo before: $before;
|
|
echo after: $after;
|
|
die Read removal used even when table has delete triggers, $after, $before - exiting;
|
|
}
|
|
|
|
# Check execute count to verify that read removal is not done for
|
|
# an update on a table which has an update trigger
|
|
CREATE TRIGGER log_updates AFTER UPDATE ON main FOR EACH ROW
|
|
INSERT INTO log (bug_text) VALUES ("one row updated");
|
|
|
|
let $before= `select VARIABLE_VALUE from performance_schema.session_status
|
|
where variable_name like 'NDB_EXECUTE_COUNT'`;
|
|
eval UPDATE main SET val = 111 WHERE id = 1;
|
|
let $after= `select VARIABLE_VALUE from performance_schema.session_status
|
|
where variable_name like 'NDB_EXECUTE_COUNT'`;
|
|
if (!`select $after-$before >= 3`)
|
|
{
|
|
enable_result_log;
|
|
echo before: $before;
|
|
echo after: $after;
|
|
die Read removal used even when table has update triggers, $after, $before - exiting;
|
|
}
|
|
|
|
### Cleanup
|
|
# Drop test tables
|
|
drop table t1, data_t1;
|
|
drop table t2, data_t2;
|
|
drop table t3, data_t3;
|
|
drop table t4, data_t4;
|
|
drop table t5, data_t5;
|
|
|
|
drop trigger log_deletes;
|
|
drop trigger log_updates;
|
|
drop table main;
|
|
drop table log;
|
|
|
|
# Drop parameter tables
|
|
drop table rbwr_tests;
|
|
|
|
--enable_query_log
|
|
--enable_result_log
|
|
|
|
if ($ndb_rbwr_fail)
|
|
{
|
|
die Test failure detected!;
|
|
}
|
|
|
|
|