diff --git a/mysql-test/suite/versioning/common.inc b/mysql-test/suite/versioning/common.inc index 6306e9e9ed382..6723395f92f42 100644 --- a/mysql-test/suite/versioning/common.inc +++ b/mysql-test/suite/versioning/common.inc @@ -10,9 +10,9 @@ begin select @i:= @i + 1 as No, trx_id > 0 as A, - begin_ts > '1-1-1 0:0:0' as B, - commit_ts > begin_ts as C, - concurr_trx is null as D + commit_id >= trx_id as B, + begin_ts > '1-1-1 0:0:0' as C, + commit_ts > begin_ts as D from information_schema.innodb_vtq where trx_id > @start_trx_id; select ifnull(max(trx_id), 0) diff --git a/mysql-test/suite/versioning/r/auto_increment.result b/mysql-test/suite/versioning/r/auto_increment.result index 9dc0075d06da3..812229638262b 100644 --- a/mysql-test/suite/versioning/r/auto_increment.result +++ b/mysql-test/suite/versioning/r/auto_increment.result @@ -6,9 +6,9 @@ set @i= 0; select @i:= @i + 1 as No, trx_id > 0 as A, -begin_ts > '1-1-1 0:0:0' as B, -commit_ts > begin_ts as C, -concurr_trx is null as D +commit_id >= trx_id as B, +begin_ts > '1-1-1 0:0:0' as C, +commit_ts > begin_ts as D from information_schema.innodb_vtq where trx_id > @start_trx_id; select ifnull(max(trx_id), 0) @@ -93,7 +93,7 @@ A x y x y 1 5 15 5 15 1 6 16 6 16 1 7 17 7 17 -call test_01('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); A x y x y 1 1 11 1 11 1 2 12 2 12 diff --git a/mysql-test/suite/versioning/r/commit_id.result b/mysql-test/suite/versioning/r/commit_id.result new file mode 100644 index 0000000000000..bb70b239fa0d3 --- /dev/null +++ b/mysql-test/suite/versioning/r/commit_id.result @@ -0,0 +1,103 @@ +set @@session.time_zone='+00:00'; +select ifnull(max(trx_id), 0) into @start_trx_id from information_schema.innodb_vtq; +create procedure if not exists verify_vtq() +begin +set @i= 0; +select +@i:= @i + 1 as No, +trx_id > 0 as A, +commit_id >= trx_id as B, +begin_ts > '1-1-1 0:0:0' as C, +commit_ts > begin_ts as D +from information_schema.innodb_vtq +where trx_id > @start_trx_id; +select ifnull(max(trx_id), 0) +into @start_trx_id +from information_schema.innodb_vtq; +end~~ +create table t1( +id int auto_increment primary key) +with system versioning +engine innodb; +set transaction isolation level read uncommitted; +insert into t1 values (); +select iso_level = 'RU' from information_schema.innodb_vtq limit 1; +iso_level = 'RU' +1 +set transaction isolation level read committed; +insert into t1 values (); +select iso_level = 'RC' from information_schema.innodb_vtq limit 1; +iso_level = 'RC' +1 +set transaction isolation level serializable; +insert into t1 values (); +select iso_level = 'S' from information_schema.innodb_vtq limit 1; +iso_level = 'S' +1 +set transaction isolation level repeatable read; +insert into t1 values (); +select iso_level = 'RR' from information_schema.innodb_vtq limit 1; +iso_level = 'RR' +1 +set @ts0= now(6); +insert into t1 values (); +select sys_trx_start from t1 where id = last_insert_id() into @tx0; +select trx_id = @tx0 from information_schema.innodb_vtq limit 1; +trx_id = @tx0 +1 +set @ts1= now(6); +insert into t1 values (); +select sys_trx_start from t1 where id = last_insert_id() into @tx1; +select trx_id = @tx1 from information_schema.innodb_vtq limit 1; +trx_id = @tx1 +1 +set @ts2= now(6); +insert into t1 values (); +select sys_trx_start from t1 where id = last_insert_id() into @tx2; +select trx_id = @tx2 from information_schema.innodb_vtq limit 1; +trx_id = @tx2 +1 +set @ts3= now(6); +select +vtq_trx_id(@ts0) < @tx0 as A, +vtq_trx_id(@ts0, true) = @tx0 as B, +vtq_trx_id(@ts1) = @tx0 as C, +vtq_trx_id(@ts1, true) = @tx1 as D, +vtq_trx_id(@ts2) = @tx1 as E, +vtq_trx_id(@ts2, true) = @tx2 as F, +vtq_trx_id(@ts3) = @tx2 as G, +vtq_trx_id(@ts3, true) is null as H; +A B C D E F G H +1 1 1 1 1 1 1 1 +select +vtq_commit_id(@ts0) < @tx0 as A, +vtq_commit_id(@ts0, true) = vtq_commit_id(null, @tx0) as B, +vtq_commit_id(@ts1) = vtq_commit_id(null, @tx0) as C, +vtq_commit_id(@ts1, true) = vtq_commit_id(null, @tx1) as D, +vtq_commit_id(@ts2) = vtq_commit_id(null, @tx1) as E, +vtq_commit_id(@ts2, true) = vtq_commit_id(null, @tx2) as F, +vtq_commit_id(@ts3) = vtq_commit_id(null, @tx2) as G, +vtq_commit_id(@ts3, true) is null as H; +A B C D E F G H +1 1 1 1 1 1 1 1 +select +vtq_trx_sees(@tx1, @tx0) as A, +not vtq_trx_sees(@tx0, @tx1) as B, +vtq_trx_sees_eq(@tx1, @tx1) as C, +not vtq_trx_sees(@tx1, @tx1) as D, +vtq_trx_sees(@tx2, 0) as E, +vtq_trx_sees(0, @tx2) is null as F, +vtq_trx_sees(-1, @tx2) as H; +A B C D E F H +1 1 1 1 1 1 1 +drop table t1; +call verify_vtq; +No A B C D +1 1 1 1 1 +2 1 1 1 1 +3 1 1 1 1 +4 1 1 1 1 +5 1 1 1 1 +6 1 1 1 1 +7 1 1 1 1 +drop procedure verify_vtq; diff --git a/mysql-test/suite/versioning/r/delete.result b/mysql-test/suite/versioning/r/delete.result index 2d604ff3381fd..e8e7ba349197b 100644 --- a/mysql-test/suite/versioning/r/delete.result +++ b/mysql-test/suite/versioning/r/delete.result @@ -6,9 +6,9 @@ set @i= 0; select @i:= @i + 1 as No, trx_id > 0 as A, -begin_ts > '1-1-1 0:0:0' as B, -commit_ts > begin_ts as C, -concurr_trx is null as D +commit_id >= trx_id as B, +begin_ts > '1-1-1 0:0:0' as C, +commit_ts > begin_ts as D from information_schema.innodb_vtq where trx_id > @start_trx_id; select ifnull(max(trx_id), 0) @@ -164,8 +164,8 @@ XNo sys_end < '2038-01-19 03:14:07' 7 1 8 1 9 1 -call test_01('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); -XNo commit_ts(sys_end) < '2038-01-19 03:14:07' +call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +XNo vtq_commit_ts(sys_end) < '2038-01-19 03:14:07' 0 0 1 0 2 0 @@ -176,7 +176,7 @@ XNo commit_ts(sys_end) < '2038-01-19 03:14:07' 7 0 8 0 9 0 -XNo commit_ts(sys_end) < '2038-01-19 03:14:07' +XNo vtq_commit_ts(sys_end) < '2038-01-19 03:14:07' 0 1 1 0 2 0 @@ -187,7 +187,7 @@ XNo commit_ts(sys_end) < '2038-01-19 03:14:07' 7 0 8 0 9 0 -XNo commit_ts(sys_end) < '2038-01-19 03:14:07' +XNo vtq_commit_ts(sys_end) < '2038-01-19 03:14:07' 0 1 1 1 2 0 @@ -207,7 +207,7 @@ XNo 2 4 5 -XNo commit_ts(sys_end) < '2038-01-19 03:14:07' +XNo vtq_commit_ts(sys_end) < '2038-01-19 03:14:07' 0 1 1 1 2 0 @@ -239,7 +239,7 @@ call test_02('timestamp(6)', 'myisam', 'sys_end'); x sys_start sys_end A B C 1 1 1 -call test_02('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_02('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); x sys_start sys_end A B C 1 1 1 @@ -273,7 +273,7 @@ t2_x_all 12 13 14 -call test_03('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); t1_x 1 2 diff --git a/mysql-test/suite/versioning/r/insert.result b/mysql-test/suite/versioning/r/insert.result index 343abb7978c5d..fdac34f6759cb 100644 --- a/mysql-test/suite/versioning/r/insert.result +++ b/mysql-test/suite/versioning/r/insert.result @@ -6,9 +6,9 @@ set @i= 0; select @i:= @i + 1 as No, trx_id > 0 as A, -begin_ts > '1-1-1 0:0:0' as B, -commit_ts > begin_ts as C, -concurr_trx is null as D +commit_id >= trx_id as B, +begin_ts > '1-1-1 0:0:0' as C, +commit_ts > begin_ts as D from information_schema.innodb_vtq where trx_id > @start_trx_id; select ifnull(max(trx_id), 0) @@ -156,8 +156,8 @@ x y sys_end 3 4 2038-01-19 03:14:07.000000 2 3 2038-01-19 03:14:07.000000 40 33 2038-01-19 03:14:07.000000 -call test_01('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); -x y commit_ts(sys_end) +call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +x y vtq_commit_ts(sys_end) 3 4 2038-01-19 03:14:07.000000 2 3 2038-01-19 03:14:07.000000 40 33 2038-01-19 03:14:07.000000 @@ -166,8 +166,8 @@ id x y sys_end 1 33 44 2038-01-19 03:14:07.000000 20 33 44 2038-01-19 03:14:07.000000 40 33 44 2038-01-19 03:14:07.000000 -call test_02('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); -id x y commit_ts(sys_end) +call test_02('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +id x y vtq_commit_ts(sys_end) 1 33 44 2038-01-19 03:14:07.000000 20 33 44 2038-01-19 03:14:07.000000 40 33 44 2038-01-19 03:14:07.000000 @@ -194,8 +194,8 @@ ERROR HY000: Generated field for System Versioning cannot be set by user drop table t1; drop view vt1_1; drop view vt1_2; -call test_03('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); -x y commit_ts(sys_end) +call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); +x y vtq_commit_ts(sys_end) 8001 9001 2038-01-19 03:14:07.000000 1001 2001 2038-01-19 03:14:07.000000 1002 2002 2038-01-19 03:14:07.000000 @@ -205,7 +205,7 @@ x y 1001 2001 1002 2002 3001 4001 -x y commit_ts(sys_end) +x y vtq_commit_ts(sys_end) 8001 9001 2038-01-19 03:14:07.000000 1001 2001 2038-01-19 03:14:07.000000 1002 2002 2038-01-19 03:14:07.000000 @@ -222,7 +222,7 @@ id a b 1 1 1 id a b C D 2 2 2 1 1 -call test_04('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_04('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); id a b 1 1 1 id a b C D @@ -257,7 +257,7 @@ x y 7 7001 8 8001 9 9001 -call test_05('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_05('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); x y 1 1001 2 2001 diff --git a/mysql-test/suite/versioning/r/optimized_fields.result b/mysql-test/suite/versioning/r/optimized_fields.result index 2e26643096793..aa1f1d3696b40 100644 --- a/mysql-test/suite/versioning/r/optimized_fields.result +++ b/mysql-test/suite/versioning/r/optimized_fields.result @@ -17,50 +17,50 @@ a b b+0 1 NULL NULL 3 NULL NULL Warnings: -Warning 4050 Attempt to read unversioned field 'b' in historical query +Warning 4067 Attempt to read unversioned field 'b' in historical query select * from t for system_time as of timestamp now(6); a b 1 NULL 3 NULL Warnings: -Warning 4050 Attempt to read unversioned field 'b' in historical query +Warning 4067 Attempt to read unversioned field 'b' in historical query select count(*) from t group by b for system_time as of timestamp now(6); count(*) 2 Warnings: -Warning 4050 Attempt to read unversioned field 'b' in historical query +Warning 4067 Attempt to read unversioned field 'b' in historical query select * from t for system_time as of timestamp now(6) order by b asc; a b 1 NULL 3 NULL Warnings: -Warning 4050 Attempt to read unversioned field 'b' in historical query +Warning 4067 Attempt to read unversioned field 'b' in historical query select * from t for system_time as of timestamp now(6) order by b desc; a b 1 NULL 3 NULL Warnings: -Warning 4050 Attempt to read unversioned field 'b' in historical query +Warning 4067 Attempt to read unversioned field 'b' in historical query select * from t group by a having a=2 for system_time as of timestamp now(6); a b Warnings: -Warning 4050 Attempt to read unversioned field 'b' in historical query +Warning 4067 Attempt to read unversioned field 'b' in historical query select * from t group by b having b=2 for system_time as of timestamp now(6); a b Warnings: -Warning 4050 Attempt to read unversioned field 'b' in historical query +Warning 4067 Attempt to read unversioned field 'b' in historical query select a from t where b=2 for system_time as of timestamp now(6); a Warnings: -Warning 4050 Attempt to read unversioned field 'b' in historical query +Warning 4067 Attempt to read unversioned field 'b' in historical query select a from t where b=NULL for system_time as of timestamp now(6); a Warnings: -Warning 4050 Attempt to read unversioned field 'b' in historical query +Warning 4067 Attempt to read unversioned field 'b' in historical query select count(*), b from t group by b having b=NULL for system_time as of timestamp now(6); count(*) b Warnings: -Warning 4050 Attempt to read unversioned field 'b' in historical query +Warning 4067 Attempt to read unversioned field 'b' in historical query select a, b from t; a b 1 2 diff --git a/mysql-test/suite/versioning/r/select.result b/mysql-test/suite/versioning/r/select.result index da8cb25340e00..92e5c25fc6ece 100644 --- a/mysql-test/suite/versioning/r/select.result +++ b/mysql-test/suite/versioning/r/select.result @@ -6,9 +6,9 @@ set @i= 0; select @i:= @i + 1 as No, trx_id > 0 as A, -begin_ts > '1-1-1 0:0:0' as B, -commit_ts > begin_ts as C, -concurr_trx is null as D +commit_id >= trx_id as B, +begin_ts > '1-1-1 0:0:0' as C, +commit_ts > begin_ts as D from information_schema.innodb_vtq where trx_id > @start_trx_id; select ifnull(max(trx_id), 0) @@ -51,7 +51,7 @@ insert into t1(x, y) values(3, 33); select sys_start from t1 where x = 3 and y = 33 into @t1; if engine = 'innodb' then set @x1= @t1; -select commit_ts(@x1) into @t1; +select vtq_commit_ts(@x1) into @t1; end if; select x, y from t1; select x as ASOF_x, y from t1 for system_time as of timestamp @t0; @@ -169,7 +169,7 @@ BETWAND_ext_x y 8 108 9 109 3 33 -call test_01('bigint unsigned', 'innodb', 'commit_ts(sys_start)'); +call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_start)'); x y 0 100 1 101 @@ -326,7 +326,7 @@ RJ2_x1 y1 x2 y2 1 3 1 2 NULL NULL 2 1 NULL NULL 3 1 -call test_02('bigint unsigned', 'innodb', 'commit_ts(sys_start)'); +call test_02('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_start)'); IJ1_x1 y1 x2 y2 1 1 1 2 1 2 1 2 diff --git a/mysql-test/suite/versioning/r/update.result b/mysql-test/suite/versioning/r/update.result index ff0874799b02b..da626cf425de2 100644 --- a/mysql-test/suite/versioning/r/update.result +++ b/mysql-test/suite/versioning/r/update.result @@ -6,9 +6,9 @@ set @i= 0; select @i:= @i + 1 as No, trx_id > 0 as A, -begin_ts > '1-1-1 0:0:0' as B, -commit_ts > begin_ts as C, -concurr_trx is null as D +commit_id >= trx_id as B, +begin_ts > '1-1-1 0:0:0' as C, +commit_ts > begin_ts as D from information_schema.innodb_vtq where trx_id > @start_trx_id; select ifnull(max(trx_id), 0) @@ -258,7 +258,7 @@ x y 9 9001 8 8000 9 9000 -call test_01('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); x y 1 1000 2 2000 @@ -296,7 +296,7 @@ A1 x y 1 11 11 A2 x 1 11 -call test_02('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_02('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); A1 x y 1 11 11 A2 x @@ -308,7 +308,7 @@ x y 3 3 3 1 3 2 -call test_03('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); x y 1 1 2 1 @@ -322,7 +322,7 @@ x 2 x 3 -call test_04('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_04('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); x x 1 @@ -356,7 +356,7 @@ x y 7 7000 8 8000 9 9000 -call test_05('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_05('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); x y 1 1000 2 2000 @@ -431,7 +431,7 @@ x y 7 7010 8 8010 9 9010 -call test_06('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_06('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); x y 1 1000 2 2000 @@ -489,7 +489,7 @@ B1 salary 1 2500 B2 salary 1 2500 -call test_07('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_07('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); A1 name 1 Jerry A2 name diff --git a/mysql-test/suite/versioning/t/auto_increment.test b/mysql-test/suite/versioning/t/auto_increment.test index 978a0eec9d435..ee5cb9411d0b6 100644 --- a/mysql-test/suite/versioning/t/auto_increment.test +++ b/mysql-test/suite/versioning/t/auto_increment.test @@ -60,7 +60,7 @@ end~~ delimiter ;~~ call test_01('timestamp(6)', 'myisam', 'sys_end'); -call test_01('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); call verify_vtq; drop procedure test_01; diff --git a/mysql-test/suite/versioning/t/commit_id.test b/mysql-test/suite/versioning/t/commit_id.test new file mode 100644 index 0000000000000..9f06e8a5b5048 --- /dev/null +++ b/mysql-test/suite/versioning/t/commit_id.test @@ -0,0 +1,79 @@ +-- source suite/versioning/common.inc + +create table t1( + id int auto_increment primary key) +with system versioning +engine innodb; + + + +# VTQ_ISO_LEVEL # + +set transaction isolation level read uncommitted; +insert into t1 values (); +select iso_level = 'RU' from information_schema.innodb_vtq limit 1; + +set transaction isolation level read committed; +insert into t1 values (); +select iso_level = 'RC' from information_schema.innodb_vtq limit 1; + +set transaction isolation level serializable; +insert into t1 values (); +select iso_level = 'S' from information_schema.innodb_vtq limit 1; + +set transaction isolation level repeatable read; +insert into t1 values (); +select iso_level = 'RR' from information_schema.innodb_vtq limit 1; + + +# VTQ_TRX_ID, VTQ_COMMIT_ID, VTQ_TRX_SEES # + +set @ts0= now(6); +insert into t1 values (); +select sys_trx_start from t1 where id = last_insert_id() into @tx0; +select trx_id = @tx0 from information_schema.innodb_vtq limit 1; + +set @ts1= now(6); +insert into t1 values (); +select sys_trx_start from t1 where id = last_insert_id() into @tx1; +select trx_id = @tx1 from information_schema.innodb_vtq limit 1; + +set @ts2= now(6); +insert into t1 values (); +select sys_trx_start from t1 where id = last_insert_id() into @tx2; +select trx_id = @tx2 from information_schema.innodb_vtq limit 1; + +set @ts3= now(6); + +select + vtq_trx_id(@ts0) < @tx0 as A, + vtq_trx_id(@ts0, true) = @tx0 as B, + vtq_trx_id(@ts1) = @tx0 as C, + vtq_trx_id(@ts1, true) = @tx1 as D, + vtq_trx_id(@ts2) = @tx1 as E, + vtq_trx_id(@ts2, true) = @tx2 as F, + vtq_trx_id(@ts3) = @tx2 as G, + vtq_trx_id(@ts3, true) is null as H; + +select + vtq_commit_id(@ts0) < @tx0 as A, + vtq_commit_id(@ts0, true) = vtq_commit_id(null, @tx0) as B, + vtq_commit_id(@ts1) = vtq_commit_id(null, @tx0) as C, + vtq_commit_id(@ts1, true) = vtq_commit_id(null, @tx1) as D, + vtq_commit_id(@ts2) = vtq_commit_id(null, @tx1) as E, + vtq_commit_id(@ts2, true) = vtq_commit_id(null, @tx2) as F, + vtq_commit_id(@ts3) = vtq_commit_id(null, @tx2) as G, + vtq_commit_id(@ts3, true) is null as H; + +select + vtq_trx_sees(@tx1, @tx0) as A, + not vtq_trx_sees(@tx0, @tx1) as B, + vtq_trx_sees_eq(@tx1, @tx1) as C, + not vtq_trx_sees(@tx1, @tx1) as D, + vtq_trx_sees(@tx2, 0) as E, + vtq_trx_sees(0, @tx2) is null as F, + vtq_trx_sees(-1, @tx2) as H; + +drop table t1; +call verify_vtq; +drop procedure verify_vtq; diff --git a/mysql-test/suite/versioning/t/delete.test b/mysql-test/suite/versioning/t/delete.test index 48bec973cee83..320efd29d56cd 100644 --- a/mysql-test/suite/versioning/t/delete.test +++ b/mysql-test/suite/versioning/t/delete.test @@ -101,17 +101,17 @@ delimiter ;~~ --echo # Basic + delete from view call test_01('timestamp(6)', 'myisam', 'sys_end'); -call test_01('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); call verify_vtq; --echo # Check sys_start, sys_end call test_02('timestamp(6)', 'myisam', 'sys_end'); -call test_02('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_02('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); call verify_vtq; --echo # Multi-delete call test_03('timestamp(6)', 'myisam', 'sys_end'); -call test_03('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); call verify_vtq; drop procedure test_01; diff --git a/mysql-test/suite/versioning/t/insert.test b/mysql-test/suite/versioning/t/insert.test index e13a5d0516a86..80eded07d2cbf 100644 --- a/mysql-test/suite/versioning/t/insert.test +++ b/mysql-test/suite/versioning/t/insert.test @@ -144,10 +144,10 @@ end~~ delimiter ;~~ call test_01('timestamp(6)', 'myisam', 'sys_end'); -call test_01('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); call test_02('timestamp(6)', 'myisam', 'sys_end'); -call test_02('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_02('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); call test_03('timestamp(6)', 'myisam', 'sys_end'); --ERROR ER_GENERATED_FIELD_CANNOT_BE_SET_BY_USER @@ -158,7 +158,7 @@ drop table t1; drop view vt1_1; drop view vt1_2; -call test_03('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); --ERROR ER_GENERATED_FIELD_CANNOT_BE_SET_BY_USER insert into t1(x, y, sys_end) values(8001, 9001, 1111111); --ERROR ER_GENERATED_FIELD_CANNOT_BE_SET_BY_USER @@ -168,10 +168,10 @@ drop view vt1_1; drop view vt1_2; call test_04('timestamp(6)', 'myisam', 'sys_end'); -call test_04('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_04('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); call test_05('timestamp(6)', 'myisam', 'sys_end'); -call test_05('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_05('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); # VTQ test diff --git a/mysql-test/suite/versioning/t/select.test b/mysql-test/suite/versioning/t/select.test index 6c586ccd86870..3db024b6624ff 100644 --- a/mysql-test/suite/versioning/t/select.test +++ b/mysql-test/suite/versioning/t/select.test @@ -39,7 +39,7 @@ begin select sys_start from t1 where x = 3 and y = 33 into @t1; if engine = 'innodb' then set @x1= @t1; - select commit_ts(@x1) into @t1; + select vtq_commit_ts(@x1) into @t1; end if; select x, y from t1; @@ -102,10 +102,10 @@ end~~ delimiter ;~~ call test_01('timestamp(6)', 'myisam', 'sys_start'); -call test_01('bigint unsigned', 'innodb', 'commit_ts(sys_start)'); +call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_start)'); call test_02('timestamp(6)', 'myisam', 'sys_start'); -call test_02('bigint unsigned', 'innodb', 'commit_ts(sys_start)'); +call test_02('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_start)'); # Test wildcard expansion on hidden fields. create table t1( diff --git a/mysql-test/suite/versioning/t/update.test b/mysql-test/suite/versioning/t/update.test index 9ca7fee412665..861e5dd66eb6e 100644 --- a/mysql-test/suite/versioning/t/update.test +++ b/mysql-test/suite/versioning/t/update.test @@ -234,25 +234,25 @@ end~~ delimiter ;~~ call test_01('timestamp(6)', 'myisam', 'sys_end'); -call test_01('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_01('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); call test_02('timestamp(6)', 'myisam', 'sys_end'); -call test_02('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_02('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); call test_03('timestamp(6)', 'myisam', 'sys_end'); -call test_03('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); call test_04('timestamp(6)', 'myisam', 'sys_end'); -call test_04('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_04('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); call test_05('timestamp(6)', 'myisam', 'sys_end'); -call test_05('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_05('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); call test_06('timestamp(6)', 'myisam', 'sys_end'); -call test_06('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_06('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); call test_07('timestamp(6)', 'myisam', 'sys_end'); -call test_07('bigint unsigned', 'innodb', 'commit_ts(sys_end)'); +call test_07('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)'); call verify_vtq; diff --git a/sql/handler.h b/sql/handler.h index 11b71a6f03dc1..964880b0b62d6 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1391,7 +1391,9 @@ struct handlerton System Versioning */ bool versioned() const; - bool (*vers_get_vtq_ts)(THD* thd, MYSQL_TIME *out, ulonglong trx_id, vtq_field_t field); + bool (*vers_query_trx_id)(THD* thd, void *out, ulonglong trx_id, vtq_field_t field); + bool (*vers_query_commit_ts)(THD* thd, void *out, const MYSQL_TIME &commit_ts, vtq_field_t field, bool backwards); + bool (*vers_trx_sees)(THD *thd, bool &result, ulonglong trx_id1, ulonglong trx_id0, ulonglong commit_id1, uchar iso_level1, ulonglong commit_id0); }; diff --git a/sql/item.h b/sql/item.h index 35b76a3278e9b..b7381bde26098 100644 --- a/sql/item.h +++ b/sql/item.h @@ -480,9 +480,20 @@ class String_copier_for_item: public String_copier String_copier_for_item(THD *thd): m_thd(thd) { } }; +/* System versioning */ +class Vers_extended_item +{ +public: + virtual vtq_record_t* vtq_cached_result() + { + return NULL; + } +}; + class Item: public Value_source, - public Type_std_attributes + public Type_std_attributes, + public Vers_extended_item { void operator=(Item &); /** diff --git a/sql/item_create.cc b/sql/item_create.cc index 48055ccb11ea3..7e8c60591e6f8 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -6678,24 +6678,26 @@ Create_func_year_week::create_native(THD *thd, LEX_STRING name, } -/* System Versioning: BEGIN_TS(), COMMIT_TS() */ - -class Create_func_begin_ts : public Create_native_func +/* System Versioning: VTQ_TRX_ID(), VTQ_COMMIT_ID(), VTQ_BEGIN_TS(), VTQ_COMMIT_TS(), VTQ_ISO_LEVEL() */ +template +class Create_func_vtq : public Create_native_func { public: virtual Item *create_native(THD *thd, LEX_STRING name, List *item_list); - static Create_func_begin_ts s_singleton; + static Create_func_vtq s_singleton; protected: - Create_func_begin_ts() {} - virtual ~Create_func_begin_ts() {} + Create_func_vtq() {} + virtual ~Create_func_vtq() {} }; -Create_func_begin_ts Create_func_begin_ts::s_singleton; +template +Create_func_vtq Create_func_vtq::s_singleton; +template Item* -Create_func_begin_ts::create_native(THD *thd, LEX_STRING name, +Create_func_vtq::create_native(THD *thd, LEX_STRING name, List *item_list) { Item *func= NULL; @@ -6708,9 +6710,38 @@ Create_func_begin_ts::create_native(THD *thd, LEX_STRING name, case 1: { Item *param_1= item_list->pop(); - func= new (thd->mem_root) Item_func_vtq_ts(thd, param_1, VTQ_BEGIN_TS); + switch (VTQ_FIELD) + { + case VTQ_BEGIN_TS: + case VTQ_COMMIT_TS: + func= new (thd->mem_root) Item_func_vtq_ts(thd, param_1, VTQ_FIELD); + break; + case VTQ_TRX_ID: + case VTQ_COMMIT_ID: + case VTQ_ISO_LEVEL: + func= new (thd->mem_root) Item_func_vtq_id(thd, param_1, VTQ_FIELD); + break; + default: + DBUG_ASSERT(0); + } + break; + } + case 2: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + switch (VTQ_FIELD) + { + case VTQ_TRX_ID: + case VTQ_COMMIT_ID: + func= new (thd->mem_root) Item_func_vtq_id(thd, param_1, param_2, VTQ_FIELD); + break; + default: + goto error; + } break; } + error: default: { my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); @@ -6719,49 +6750,45 @@ Create_func_begin_ts::create_native(THD *thd, LEX_STRING name, } return func; -} +}; -class Create_func_commit_ts : public Create_native_func +template +class Create_func_vtq_trx_sees : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_STRING name, List *item_list); - - static Create_func_commit_ts s_singleton; - -protected: - Create_func_commit_ts() {} - virtual ~Create_func_commit_ts() {} -}; - -Create_func_commit_ts Create_func_commit_ts::s_singleton; + virtual Item *create_native(THD *thd, LEX_STRING name, List *item_list) + { + Item *func= NULL; + int arg_count= 0; -Item* -Create_func_commit_ts::create_native(THD *thd, LEX_STRING name, - List *item_list) -{ - Item *func= NULL; - int arg_count= 0; + if (item_list != NULL) + arg_count= item_list->elements; - if (item_list != NULL) - arg_count= item_list->elements; + switch (arg_count) { + case 2: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + func= new (thd->mem_root) Item_func_vtq_trx_seesX(thd, param_1, param_2); + break; + } + default: + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + break; + } - switch (arg_count) { - case 1: - { - Item *param_1= item_list->pop(); - func= new (thd->mem_root) Item_func_vtq_ts(thd, param_1, VTQ_COMMIT_TS); - break; - } - default: - { - my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); - break; - } + return func; } - return func; -} + static Create_func_vtq_trx_sees s_singleton; + +protected: + Create_func_vtq_trx_sees() {} + virtual ~Create_func_vtq_trx_sees() {} +}; +template +Create_func_vtq_trx_sees Create_func_vtq_trx_sees::s_singleton; struct Native_func_registry @@ -6804,7 +6831,6 @@ static Native_func_registry func_array[] = { { C_STRING_WITH_LEN("ASWKT") }, GEOM_BUILDER(Create_func_as_wkt)}, { { C_STRING_WITH_LEN("ATAN") }, BUILDER(Create_func_atan)}, { { C_STRING_WITH_LEN("ATAN2") }, BUILDER(Create_func_atan)}, - { { C_STRING_WITH_LEN("BEGIN_TS") }, BUILDER(Create_func_begin_ts)}, { { C_STRING_WITH_LEN("BENCHMARK") }, BUILDER(Create_func_benchmark)}, { { C_STRING_WITH_LEN("BIN") }, BUILDER(Create_func_bin)}, { { C_STRING_WITH_LEN("BINLOG_GTID_POS") }, BUILDER(Create_func_binlog_gtid_pos)}, @@ -6822,7 +6848,6 @@ static Native_func_registry func_array[] = { { C_STRING_WITH_LEN("COLUMN_EXISTS") }, BUILDER(Create_func_dyncol_exists)}, { { C_STRING_WITH_LEN("COLUMN_LIST") }, BUILDER(Create_func_dyncol_list)}, { { C_STRING_WITH_LEN("COLUMN_JSON") }, BUILDER(Create_func_dyncol_json)}, - { { C_STRING_WITH_LEN("COMMIT_TS") }, BUILDER(Create_func_commit_ts)}, { { C_STRING_WITH_LEN("COMPRESS") }, BUILDER(Create_func_compress)}, { { C_STRING_WITH_LEN("CONCAT") }, BUILDER(Create_func_concat)}, { { C_STRING_WITH_LEN("CONCAT_WS") }, BUILDER(Create_func_concat_ws)}, @@ -7121,6 +7146,13 @@ static Native_func_registry func_array[] = { { C_STRING_WITH_LEN("UUID") }, BUILDER(Create_func_uuid)}, { { C_STRING_WITH_LEN("UUID_SHORT") }, BUILDER(Create_func_uuid_short)}, { { C_STRING_WITH_LEN("VERSION") }, BUILDER(Create_func_version)}, + { { C_STRING_WITH_LEN("VTQ_BEGIN_TS") }, BUILDER(Create_func_vtq)}, + { { C_STRING_WITH_LEN("VTQ_COMMIT_ID") }, BUILDER(Create_func_vtq)}, + { { C_STRING_WITH_LEN("VTQ_COMMIT_TS") }, BUILDER(Create_func_vtq)}, + { { C_STRING_WITH_LEN("VTQ_ISO_LEVEL") }, BUILDER(Create_func_vtq)}, + { { C_STRING_WITH_LEN("VTQ_TRX_ID") }, BUILDER(Create_func_vtq)}, + { { C_STRING_WITH_LEN("VTQ_TRX_SEES") }, BUILDER(Create_func_vtq_trx_sees)}, + { { C_STRING_WITH_LEN("VTQ_TRX_SEES_EQ") }, BUILDER(Create_func_vtq_trx_sees)}, { { C_STRING_WITH_LEN("WEEKDAY") }, BUILDER(Create_func_weekday)}, { { C_STRING_WITH_LEN("WEEKOFYEAR") }, BUILDER(Create_func_weekofyear)}, { { C_STRING_WITH_LEN("WITHIN") }, GEOM_BUILDER(Create_func_within)}, diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 3ceb87246ce05..1f9d107606012 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -3278,10 +3278,9 @@ Item_func_vtq_ts::Item_func_vtq_ts( THD *thd, Item* a, vtq_field_t _vtq_field, - handlerton* _hton) : - Item_datetimefunc(thd, a), - vtq_field(_vtq_field), - hton(_hton) + handlerton* hton) : + VTQ_common(thd, a, hton), + vtq_field(_vtq_field) { decimals= 6; null_value= true; @@ -3292,33 +3291,24 @@ Item_func_vtq_ts::Item_func_vtq_ts( THD *thd, Item* a, vtq_field_t _vtq_field) : - Item_datetimefunc(thd, a), - vtq_field(_vtq_field), - hton(NULL) + VTQ_common(thd, a), + vtq_field(_vtq_field) { decimals= 6; null_value= true; DBUG_ASSERT(arg_count == 1 && args[0]); } -bool Item_func_vtq_ts::get_date(MYSQL_TIME *res, ulonglong fuzzy_date) +template +void +VTQ_common::init_hton() { - THD *thd= current_thd; // can it differ from constructor's? - DBUG_ASSERT(thd); - ulonglong trx_id= args[0]->val_uint(); - if (trx_id == ULONGLONG_MAX) - { - null_value= false; - thd->variables.time_zone->gmt_sec_to_TIME(res, TIMESTAMP_MAX_VALUE); - return false; - } - if (!hton) { - if (args[0]->type() == Item::FIELD_ITEM) + if (Item_func_X::args[0]->type() == Item::FIELD_ITEM) { Item_field *f= - static_cast(args[0]); + static_cast(Item_func_X::args[0]); DBUG_ASSERT( f->field && f->field->table && @@ -3333,11 +3323,201 @@ bool Item_func_vtq_ts::get_date(MYSQL_TIME *res, ulonglong fuzzy_date) DBUG_ASSERT(hton); } } +} + +bool +Item_func_vtq_ts::get_date(MYSQL_TIME *res, ulonglong fuzzy_date) +{ + THD *thd= current_thd; // can it differ from constructor's? + DBUG_ASSERT(thd); + ulonglong trx_id= args[0]->val_uint(); + if (trx_id == ULONGLONG_MAX) + { + null_value= false; + thd->variables.time_zone->gmt_sec_to_TIME(res, TIMESTAMP_MAX_VALUE); + return false; + } + + init_hton(); if (!hton) return true; - null_value= !hton->vers_get_vtq_ts(thd, res, trx_id, vtq_field); + null_value= !hton->vers_query_trx_id(thd, res, trx_id, vtq_field); return false; } + + +Item_func_vtq_id::Item_func_vtq_id( + THD *thd, + Item* a, + vtq_field_t _vtq_field, + bool _backwards) : + VTQ_common(thd, a), + vtq_field(_vtq_field), + backwards(_backwards) +{ + memset(&cached_result, 0, sizeof(cached_result)); + decimals= 0; + unsigned_flag= 1; + null_value= true; + DBUG_ASSERT(arg_count == 1 && args[0]); +} + +Item_func_vtq_id::Item_func_vtq_id( + THD *thd, + Item* a, + Item* b, + vtq_field_t _vtq_field) : + VTQ_common(thd, a, b), + vtq_field(_vtq_field), + backwards(false) +{ + memset(&cached_result, 0, sizeof(cached_result)); + decimals= 0; + unsigned_flag= 1; + null_value= true; + DBUG_ASSERT(arg_count == 2 && args[0] && args[1]); +} + +longlong +Item_func_vtq_id::get_by_trx_id(ulonglong trx_id) +{ + ulonglong res; + THD *thd= current_thd; // can it differ from constructor's? + DBUG_ASSERT(thd); + + if (trx_id == ULONGLONG_MAX) + { + null_value= true; + return 0; + } + + null_value= !hton->vers_query_trx_id(thd, &res, trx_id, vtq_field); + return res; +} + +longlong +Item_func_vtq_id::get_by_commit_ts(MYSQL_TIME &commit_ts, bool backwards) +{ + THD *thd= current_thd; // can it differ from constructor's? + DBUG_ASSERT(thd); + + null_value= !hton->vers_query_commit_ts(thd, &cached_result, commit_ts, VTQ_ALL, backwards); + if (null_value) + { + return 0; + } + + switch (vtq_field) + { + case VTQ_COMMIT_ID: + return cached_result.commit_id; + case VTQ_ISO_LEVEL: + return cached_result.iso_level; + case VTQ_TRX_ID: + return cached_result.trx_id; + default: + DBUG_ASSERT(0); + null_value= true; + } + + return 0; +} + +longlong +Item_func_vtq_id::val_int() +{ + init_hton(); + + if (!hton) + { + null_value= true; + return 0; + } + + if (args[0]->is_null()) + { + if (arg_count < 2 || vtq_field == VTQ_TRX_ID) + { + null_value= true; + return 0; + } + return get_by_trx_id(args[1]->val_uint()); + } + else + { + MYSQL_TIME commit_ts; + if (args[0]->get_date(&commit_ts, 0)) + { + null_value= true; + return 0; + } + if (arg_count > 1) + { + backwards= args[1]->val_bool(); + DBUG_ASSERT(arg_count == 2); + } + return get_by_commit_ts(commit_ts, backwards); + } +} + +Item_func_vtq_trx_sees::Item_func_vtq_trx_sees( + THD *thd, + Item* a, + Item* b) : + VTQ_common(thd, a, b), + accept_eq(false) +{ + null_value= true; + DBUG_ASSERT(arg_count == 2 && args[0] && args[1]); +} + +longlong +Item_func_vtq_trx_sees::val_int() +{ + THD *thd= current_thd; + DBUG_ASSERT(thd); + + init_hton(); + + if (!hton) + { + null_value= true; + return 0; + } + + ulonglong trx_id1, trx_id0; + ulonglong commit_id1= 0; + ulonglong commit_id0= 0; + uchar iso_level1= 0; + + DBUG_ASSERT(arg_count > 1); + trx_id1= args[0]->val_uint(); + trx_id0= args[1]->val_uint(); + + vtq_record_t *cached= args[0]->vtq_cached_result(); + if (cached && cached->commit_id) + { + commit_id1= cached->commit_id; + iso_level1= cached->iso_level; + } + + cached= args[1]->vtq_cached_result(); + if (cached && cached->commit_id) + { + commit_id0= cached->commit_id; + } + + if (accept_eq && trx_id1 && trx_id1 == trx_id0) + { + null_value= false; + return true; + } + + bool result= false; + null_value= !hton->vers_trx_sees(thd, result, trx_id1, trx_id0, commit_id1, iso_level1, commit_id0); + return result; +} + diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index a8281124b3848..4d7935b85067f 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -1288,10 +1288,28 @@ class Item_func_last_day :public Item_datefunc #include "vtq.h" -class Item_func_vtq_ts :public Item_datetimefunc +template +class VTQ_common : public Item_func_X { - vtq_field_t vtq_field; +protected: handlerton *hton; + void init_hton(); +public: + VTQ_common(THD *thd, Item* a) : + Item_func_X(thd, a), + hton(NULL) {} + VTQ_common(THD *thd, Item* a, Item* b) : + Item_func_X(thd, a, b), + hton(NULL) {} + VTQ_common(THD *thd, Item* a, handlerton* _hton) : + Item_func_X(thd, a), + hton(_hton) {} +}; + +class Item_func_vtq_ts : + public VTQ_common +{ + vtq_field_t vtq_field; public: Item_func_vtq_ts(THD *thd, Item* a, vtq_field_t _vtq_field, handlerton *hton); Item_func_vtq_ts(THD *thd, Item* a, vtq_field_t _vtq_field); @@ -1299,13 +1317,88 @@ class Item_func_vtq_ts :public Item_datetimefunc { if (vtq_field == VTQ_BEGIN_TS) { - return "begin_ts"; + return "vtq_begin_ts"; } - return "commit_ts"; + return "vtq_commit_ts"; } bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy(thd, mem_root, this); } }; +class Item_func_vtq_id : + public VTQ_common +{ + vtq_field_t vtq_field; + vtq_record_t cached_result; + bool backwards; + + longlong get_by_trx_id(ulonglong trx_id); + longlong get_by_commit_ts(MYSQL_TIME &commit_ts, bool backwards); + +public: + Item_func_vtq_id(THD *thd, Item* a, vtq_field_t _vtq_field, bool _backwards= false); + Item_func_vtq_id(THD *thd, Item* a, Item* b, vtq_field_t _vtq_field); + + vtq_record_t *vtq_cached_result() { return &cached_result; } + + const char *func_name() const + { + switch (vtq_field) + { + case VTQ_TRX_ID: + return "vtq_trx_id"; + case VTQ_COMMIT_ID: + return "vtq_commit_id"; + case VTQ_ISO_LEVEL: + return "vtq_iso_level"; + default: + DBUG_ASSERT(0); + } + return NULL; + } + + void fix_length_and_dec() + { + Item_int_func::fix_length_and_dec(); + max_length= 20; + } + + longlong val_int(); + Item *get_copy(THD *thd, MEM_ROOT *mem_root) + { return get_item_copy(thd, mem_root, this); } +}; + +class Item_func_vtq_trx_sees : + public VTQ_common +{ +protected: + bool accept_eq; + +public: + Item_func_vtq_trx_sees(THD *thd, Item* a, Item* b); + const char *func_name() const + { + return "vtq_trx_sees"; + } + longlong val_int(); + Item *get_copy(THD *thd, MEM_ROOT *mem_root) + { return get_item_copy(thd, mem_root, this); } +}; + +class Item_func_vtq_trx_sees_eq : + public Item_func_vtq_trx_sees +{ +public: + Item_func_vtq_trx_sees_eq(THD *thd, Item* a, Item* b) : + Item_func_vtq_trx_sees(thd, a, b) + { + accept_eq= true; + } + const char *func_name() const + { + return "vtq_trx_sees_eq"; + } +}; + #endif /* ITEM_TIMEFUNC_INCLUDED */ diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 81ff9b7246a3d..4c2ba3caa022f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -671,6 +671,7 @@ static int setup_for_system_time(THD *thd, TABLE_LIST *tables, COND **where_expr, SELECT_LEX *slex) { DBUG_ENTER("setup_for_system_time"); +#define newx new (thd->mem_root) TABLE_LIST *table; int versioned_tables= 0; @@ -741,6 +742,8 @@ setup_for_system_time(THD *thd, TABLE_LIST *tables, COND **where_expr, SELECT_LE } } + const static bool vers_simple_select= false; + for (table= tables; table; table= table->next_local) { if (table->table && table->table->versioned()) @@ -758,8 +761,8 @@ setup_for_system_time(THD *thd, TABLE_LIST *tables, COND **where_expr, SELECT_LE Name_resolution_context *context= slex->parent_lex->current_context(); DBUG_ASSERT(context); - Item *row_start= new (thd->mem_root) Item_field(thd, context, fstart); - Item *row_end= new (thd->mem_root) Item_field(thd, context, fend); + Item *row_start= newx Item_field(thd, context, fstart); + Item *row_end= newx Item_field(thd, context, fend); Item *row_end2= row_end; if (table->table->versioned_by_sql()) @@ -770,58 +773,108 @@ setup_for_system_time(THD *thd, TABLE_LIST *tables, COND **where_expr, SELECT_LE DBUG_RETURN(-1); } } - else if (slex->vers_conditions.unit == UNIT_TIMESTAMP) + else if (vers_simple_select && slex->vers_conditions.unit == UNIT_TIMESTAMP + && slex->vers_conditions.type != FOR_SYSTEM_TIME_UNSPECIFIED) { DBUG_ASSERT(table->table->s && table->table->s->db_plugin); - row_start= new (thd->mem_root) Item_func_vtq_ts( + handlerton *hton= plugin_hton(table->table->s->db_plugin); + DBUG_ASSERT(hton); + row_start= newx Item_func_vtq_ts( thd, row_start, VTQ_COMMIT_TS, - plugin_hton(table->table->s->db_plugin)); - row_end= new (thd->mem_root) Item_func_vtq_ts( + // FIXME: is it needed to pass hton or it can be deduced from arg 'a'? + hton); + row_end= newx Item_func_vtq_ts( thd, row_end, VTQ_COMMIT_TS, - plugin_hton(table->table->s->db_plugin)); + hton); } Item *cond1= 0, *cond2= 0, *curr= 0; - switch (slex->vers_conditions.type) + if (table->table->versioned_by_sql() || vers_simple_select) { + switch (slex->vers_conditions.type) + { case FOR_SYSTEM_TIME_UNSPECIFIED: if (table->table->versioned_by_sql()) { MYSQL_TIME max_time; thd->variables.time_zone->gmt_sec_to_TIME(&max_time, TIMESTAMP_MAX_VALUE); - curr= new (thd->mem_root) Item_datetime_literal(thd, &max_time); - cond1= new (thd->mem_root) Item_func_eq(thd, row_end, curr); + curr= newx Item_datetime_literal(thd, &max_time); + cond1= newx Item_func_eq(thd, row_end, curr); } else { - curr= new (thd->mem_root) Item_int(thd, ULONGLONG_MAX); - cond1= new (thd->mem_root) Item_func_eq(thd, row_end2, curr); + curr= newx Item_int(thd, ULONGLONG_MAX); + cond1= newx Item_func_eq(thd, row_end2, curr); } break; case FOR_SYSTEM_TIME_AS_OF: - cond1= new (thd->mem_root) Item_func_le(thd, row_start, + cond1= newx Item_func_le(thd, row_start, slex->vers_conditions.start); - cond2= new (thd->mem_root) Item_func_gt(thd, row_end, + cond2= newx Item_func_gt(thd, row_end, slex->vers_conditions.start); break; case FOR_SYSTEM_TIME_FROM_TO: - cond1= new (thd->mem_root) Item_func_lt(thd, row_start, - slex->vers_conditions.end); - cond2= new (thd->mem_root) Item_func_ge(thd, row_end, - slex->vers_conditions.start); + cond1= newx Item_func_lt(thd, row_start, + slex->vers_conditions.end); + cond2= newx Item_func_ge(thd, row_end, + slex->vers_conditions.start); + break; + case FOR_SYSTEM_TIME_BETWEEN: + cond1= newx Item_func_le(thd, row_start, + slex->vers_conditions.end); + cond2= newx Item_func_ge(thd, row_end, + slex->vers_conditions.start); + break; + default: + DBUG_ASSERT(0); + } + } + else + { + DBUG_ASSERT(table->table->s && table->table->s->db_plugin); + handlerton *hton= plugin_hton(table->table->s->db_plugin); + DBUG_ASSERT(hton); + + Item *trx_id0, *trx_id1; + + switch (slex->vers_conditions.type) + { + case FOR_SYSTEM_TIME_UNSPECIFIED: + curr= newx Item_int(thd, ULONGLONG_MAX); + cond1= newx Item_func_eq(thd, row_end2, curr); break; + case FOR_SYSTEM_TIME_AS_OF: + trx_id0= slex->vers_conditions.unit == UNIT_TIMESTAMP ? + newx Item_func_vtq_id(thd, slex->vers_conditions.start, VTQ_TRX_ID) : + slex->vers_conditions.start; + cond1= newx Item_func_vtq_trx_sees_eq(thd, trx_id0, row_start); + cond2= newx Item_func_vtq_trx_sees(thd, row_end, trx_id0); + break; + case FOR_SYSTEM_TIME_FROM_TO: case FOR_SYSTEM_TIME_BETWEEN: - cond1= new (thd->mem_root) Item_func_le(thd, row_start, - slex->vers_conditions.end); - cond2= new (thd->mem_root) Item_func_ge(thd, row_end, - slex->vers_conditions.start); + if (slex->vers_conditions.unit == UNIT_TIMESTAMP) + { + trx_id0= newx Item_func_vtq_id(thd, slex->vers_conditions.start, VTQ_TRX_ID, true); + trx_id1= newx Item_func_vtq_id(thd, slex->vers_conditions.end, VTQ_TRX_ID, false); + } + else + { + trx_id0= slex->vers_conditions.start; + trx_id1= slex->vers_conditions.end; + } + + cond1= slex->vers_conditions.type == FOR_SYSTEM_TIME_FROM_TO ? + newx Item_func_vtq_trx_sees(thd, trx_id1, row_start) : + newx Item_func_vtq_trx_sees_eq(thd, trx_id1, row_start); + cond2= newx Item_func_vtq_trx_sees_eq(thd, row_end, trx_id0); break; default: DBUG_ASSERT(0); + } } if (cond1) @@ -848,6 +901,7 @@ setup_for_system_time(THD *thd, TABLE_LIST *tables, COND **where_expr, SELECT_LE } DBUG_RETURN(0); +#undef newx } /***************************************************************************** diff --git a/sql/vtq.h b/sql/vtq.h index 3a235352853ff..68c01990b040d 100755 --- a/sql/vtq.h +++ b/sql/vtq.h @@ -17,9 +17,21 @@ enum vtq_field_t { - VTQ_BEGIN_TS = 0, - VTQ_COMMIT_TS + VTQ_ALL = 0, + VTQ_TRX_ID, + VTQ_COMMIT_ID, + VTQ_BEGIN_TS, + VTQ_COMMIT_TS, + VTQ_ISO_LEVEL }; -#endif /* VTQ_INCLUDED */ +struct vtq_record_t +{ + ulonglong trx_id; + ulonglong commit_id; + timeval begin_ts; + timeval commit_ts; + uchar iso_level; +}; +#endif /* VTQ_INCLUDED */ diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc index bb636e4f5dfdd..1fc2c99bde48e 100644 --- a/storage/innobase/btr/btr0pcur.cc +++ b/storage/innobase/btr/btr0pcur.cc @@ -657,8 +657,9 @@ btr_pcur_open_on_user_rec_func( } else { ut_ad((mode == PAGE_CUR_LE) || (mode == PAGE_CUR_L)); - /* Not implemented yet */ + if (btr_pcur_is_before_first_on_page(cursor)) { - ut_error; + btr_pcur_move_to_prev_user_rec(cursor, mtr); + } } } diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc index e3eb1004c623d..abcd8b380d951 100644 --- a/storage/innobase/dict/dict0crea.cc +++ b/storage/innobase/dict/dict0crea.cc @@ -1887,20 +1887,19 @@ dict_create_or_check_vtq_table(void) my_bool srv_file_per_table_backup; dberr_t err; dberr_t sys_vtq_err; + dict_index_t* index; ut_a(srv_get_active_thread_type() == SRV_NONE); /* Note: The master thread has not been started at this point. */ - + static const int vtq_num_indexes = 4; sys_vtq_err = dict_check_if_system_table_exists( - "SYS_VTQ", DICT_NUM_FIELDS__SYS_VTQ + 1, 3); + "SYS_VTQ", DICT_NUM_FIELDS__SYS_VTQ + 1, vtq_num_indexes); if (sys_vtq_err == DB_SUCCESS) { - mutex_enter(&dict_sys->mutex); - dict_sys->sys_vtq = dict_table_get_low("SYS_VTQ"); - mutex_exit(&dict_sys->mutex); - return(DB_SUCCESS); + err = DB_SUCCESS; + goto assign_and_exit; } trx = trx_allocate_for_mysql(); @@ -1935,10 +1934,16 @@ dict_create_or_check_vtq_table(void) "PROCEDURE CREATE_VTQ_SYS_TABLE_PROC () IS\n" "BEGIN\n" "CREATE TABLE\n" - "SYS_VTQ(TRX_ID BIGINT UNSIGNED, BEGIN_TS BIGINT UNSIGNED," - " COMMIT_TS BIGINT UNSIGNED, CONCURR_TRX BLOB);\n" + "SYS_VTQ(" + "TRX_ID BIGINT UNSIGNED, " + "COMMIT_ID BIGINT UNSIGNED, " + "BEGIN_TS BIGINT UNSIGNED, " + "COMMIT_TS BIGINT UNSIGNED, " + "ISO_LEVEL CHAR(1));\n" "CREATE UNIQUE CLUSTERED INDEX TRX_ID_IND" " ON SYS_VTQ (TRX_ID);\n" + "CREATE INDEX COMMIT_ID_IND" + " ON SYS_VTQ (COMMIT_ID);\n" "CREATE INDEX BEGIN_TS_IND" " ON SYS_VTQ (BEGIN_TS);\n" "CREATE INDEX COMMIT_TS_IND" @@ -1978,10 +1983,20 @@ dict_create_or_check_vtq_table(void) /* Note: The master thread has not been started at this point. */ /* Confirm and move to the non-LRU part of the table LRU list. */ sys_vtq_err = dict_check_if_system_table_exists( - "SYS_VTQ", DICT_NUM_FIELDS__SYS_VTQ + 1, 3); + "SYS_VTQ", DICT_NUM_FIELDS__SYS_VTQ + 1, vtq_num_indexes); ut_a(sys_vtq_err == DB_SUCCESS); + +assign_and_exit: mutex_enter(&dict_sys->mutex); dict_sys->sys_vtq = dict_table_get_low("SYS_VTQ"); + ut_ad(dict_sys->sys_vtq); + index = dict_table_get_first_index(dict_sys->sys_vtq); + for (int i = 0; i < 3; ++i) { + index = dict_table_get_next_index(index); + ut_ad(index); + } + ut_ad(strcmp(index->name, "COMMIT_TS_IND") == 0); + dict_sys->vtq_commit_ts_ind = index; mutex_exit(&dict_sys->mutex); return(err); diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index 415f5eb8531a1..fa73380fcade8 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -845,15 +845,11 @@ dict_process_sys_vtq( /*=======================*/ mem_heap_t* heap, /*!< in/out: heap memory */ const rec_t* rec, /*!< in: current rec */ -trx_id_t* col_trx_id, /*!< out: field values */ -timeval* col_begin_ts, -timeval* col_commit_ts, -char** col_concurr_trx) +vtq_record_t& out /*!< out: field values */ +) { - ulint len, col, concurr_n; - const byte *field, *ptr; - char *out; - trx_id_t trx_id; + ulint len, nfld; + const byte *field; if (rec_get_deleted_flag(rec, 0)) { return("delete-marked record in SYS_VTQ"); @@ -864,57 +860,46 @@ char** col_concurr_trx) } /* TRX_ID */ field = rec_get_nth_field_old( - rec, (col = DICT_FLD__SYS_VTQ__TRX_ID), &len); + rec, (nfld = DICT_FLD__SYS_VTQ__TRX_ID), &len); if (len != sizeof(trx_id_t)) - return dict_print_error(heap, col, len, sizeof(trx_id_t)); + return dict_print_error(heap, nfld, len, sizeof(trx_id_t)); - *col_trx_id = mach_read_from_8(field); + out.trx_id = mach_read_from_8(field); + /* COMMIT_ID */ + field = rec_get_nth_field_old( + rec, (nfld = DICT_FLD__SYS_VTQ__COMMIT_ID), &len); + + if (len != sizeof(trx_id_t)) + return dict_print_error(heap, nfld, len, sizeof(trx_id_t)); + + out.commit_id = mach_read_from_8(field); /* BEGIN_TS */ field = rec_get_nth_field_old( - rec, (col = DICT_FLD__SYS_VTQ__BEGIN_TS), &len); + rec, (nfld = DICT_FLD__SYS_VTQ__BEGIN_TS), &len); if (len != sizeof(ullong)) - return dict_print_error(heap, col, len, sizeof(ullong)); + return dict_print_error(heap, nfld, len, sizeof(ullong)); - col_begin_ts->tv_sec = mach_read_from_4(field); - col_begin_ts->tv_usec = mach_read_from_4(field + 4); + out.begin_ts.tv_sec = mach_read_from_4(field); + out.begin_ts.tv_usec = mach_read_from_4(field + 4); /* COMMIT_TS */ field = rec_get_nth_field_old( - rec, (col = DICT_FLD__SYS_VTQ__COMMIT_TS), &len); + rec, (nfld = DICT_FLD__SYS_VTQ__COMMIT_TS), &len); if (len != sizeof(ullong)) - return dict_print_error(heap, col, len, sizeof(ullong)); + return dict_print_error(heap, nfld, len, sizeof(ullong)); - col_commit_ts->tv_sec = mach_read_from_4(field); - col_commit_ts->tv_usec = mach_read_from_4(field + 4); - /* CONCURR_TRX */ + out.commit_ts.tv_sec = mach_read_from_4(field); + out.commit_ts.tv_usec = mach_read_from_4(field + 4); + /* ISOLATION_LEVEL */ field = rec_get_nth_field_old( - rec, (col = DICT_FLD__SYS_VTQ__CONCURR_TRX), &len); - concurr_n = len / sizeof(trx_id_t); - if (len != concurr_n * sizeof(trx_id_t)) - return dict_print_error(heap, col, len, concurr_n * sizeof(trx_id_t)); + rec, (nfld = DICT_FLD__SYS_VTQ__ISOLATION_LEVEL), &len); - bool truncated = false; - if (concurr_n > I_S_MAX_CONCURR_TRX) { - concurr_n = I_S_MAX_CONCURR_TRX; - truncated = true; - } + if (len != sizeof(byte)) + return dict_print_error(heap, nfld, len, sizeof(byte)); - if (concurr_n == 0) { - *col_concurr_trx = NULL; - return(NULL); - } - *col_concurr_trx = static_cast(mem_heap_alloc(heap, concurr_n * (TRX_ID_MAX_LEN + 1) + 3 + 1)); - ptr = field, out = *col_concurr_trx; - for (ulint i = 0; i < concurr_n; - ++i, ptr += sizeof(trx_id_t)) - { - trx_id = mach_read_from_8(ptr); - out += ut_snprintf(out, TRX_ID_MAX_LEN + 1, TRX_ID_FMT " ", trx_id); - } - if (truncated) - strcpy(out, "..."); + out.iso_level = *field; return(NULL); } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 18a8a9018ec13..6d7f541c74921 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -121,7 +121,6 @@ this program; if not, write to the Free Software Foundation, Inc., #include "trx0xa.h" #include "ut0mem.h" #include "row0ext.h" -#include "vtq.h" #define thd_get_trx_isolation(X) ((enum_tx_isolation)thd_tx_isolation(X)) @@ -1542,7 +1541,21 @@ innobase_fts_store_docid( #endif bool -innobase_get_vtq_ts(THD* thd, MYSQL_TIME *out, ulonglong in_trx_id, vtq_field_t field); +vtq_query_trx_id(THD* thd, void *out, ulonglong in_trx_id, vtq_field_t field); + +bool +vtq_query_commit_ts(THD* thd, void *out, const MYSQL_TIME &commit_ts, vtq_field_t field, bool backwards); + +bool +vtq_trx_sees( + THD *thd, + bool &result, + ulonglong trx_id1, + ulonglong trx_id0, + ulonglong commit_id1, + uchar iso_level1, + ulonglong commit_id0); + /*************************************************************//** Check for a valid value of innobase_commit_concurrency. @@ -3877,7 +3890,9 @@ innobase_init( innobase_hton->table_options = innodb_table_option_list; /* System Versioning */ - innobase_hton->vers_get_vtq_ts = innobase_get_vtq_ts; + innobase_hton->vers_query_trx_id = vtq_query_trx_id; + innobase_hton->vers_query_commit_ts = vtq_query_commit_ts; + innobase_hton->vers_trx_sees = vtq_trx_sees; innodb_remember_check_sysvar_funcs(); @@ -23138,25 +23153,54 @@ ib_push_frm_error( inline void -innobase_get_vtq_ts_result(THD* thd, vtq_query_t* q, MYSQL_TIME *out, vtq_field_t field) +innobase_vtq_result(THD* thd, vtq_record_t& q, void *out, vtq_field_t field) { + ut_ad(field == VTQ_ALL || out); + switch (field) { - case VTQ_BEGIN_TS: - thd_get_timezone(thd)->gmt_sec_to_TIME(out, q->begin_ts.tv_sec); - out->second_part = q->begin_ts.tv_usec; + case VTQ_ALL: + if (out) { + *reinterpret_cast(out) = q; + } + break; + case VTQ_TRX_ID: + *reinterpret_cast(out) = q.trx_id; + break; + case VTQ_COMMIT_ID: + *reinterpret_cast(out) = q.commit_id; break; - case VTQ_COMMIT_TS: - thd_get_timezone(thd)->gmt_sec_to_TIME(out, q->commit_ts.tv_sec); - out->second_part = q->commit_ts.tv_usec; + case VTQ_BEGIN_TS: { + MYSQL_TIME* out_ts = reinterpret_cast(out); + thd_get_timezone(thd)->gmt_sec_to_TIME(out_ts, q.begin_ts.tv_sec); + out_ts->second_part = q.begin_ts.tv_usec; + break; + } + case VTQ_COMMIT_TS: { + MYSQL_TIME* out_ts = reinterpret_cast(out); + thd_get_timezone(thd)->gmt_sec_to_TIME(out_ts, q.commit_ts.tv_sec); + out_ts->second_part = q.commit_ts.tv_usec; + break; + } + case VTQ_ISO_LEVEL: + *reinterpret_cast(out) = q.iso_level; break; default: ut_error; } } + +inline +const char * +vtq_query_t::cache_result(mem_heap_t* heap, const rec_t* rec) +{ + prev_query.tv_sec = 0; + return dict_process_sys_vtq(heap, rec, result); +} + UNIV_INTERN bool -innobase_get_vtq_ts(THD* thd, MYSQL_TIME *out, ulonglong _in_trx_id, vtq_field_t field) +vtq_query_trx_id(THD* thd, void *out, ulonglong _in_trx_id, vtq_field_t field) { trx_t* trx; dict_index_t* index; @@ -23167,11 +23211,9 @@ innobase_get_vtq_ts(THD* thd, MYSQL_TIME *out, ulonglong _in_trx_id, vtq_field_t mtr_t mtr; mem_heap_t* heap; rec_t* rec; - ulint len; - byte* result_net; bool found = false; - DBUG_ENTER("innobase_get_vtq_ts"); + DBUG_ENTER("vtq_query_trx_id"); if (_in_trx_id == 0) { DBUG_RETURN(false); @@ -23182,10 +23224,11 @@ innobase_get_vtq_ts(THD* thd, MYSQL_TIME *out, ulonglong _in_trx_id, vtq_field_t trx = thd_to_trx(thd); ut_a(trx); - vtq_query_t* q = &trx->vtq_query; - if (q->trx_id == in_trx_id) { - innobase_get_vtq_ts_result(thd, q, out, field); + vtq_record_t &cached = trx->vtq_query.result; + + if (cached.trx_id == in_trx_id) { + innobase_vtq_result(thd, cached, out, field); DBUG_RETURN(true); } @@ -23212,24 +23255,201 @@ innobase_get_vtq_ts(THD* thd, MYSQL_TIME *out, ulonglong _in_trx_id, vtq_field_t goto not_found; rec = btr_pcur_get_rec(&pcur); - result_net = rec_get_nth_field_old(rec, DICT_FLD__SYS_VTQ__TRX_ID, &len); - ut_ad(len == 8); - q->trx_id = mach_read_from_8(result_net); + { + const char *err = trx->vtq_query.cache_result(heap, rec); + if (err) { + fprintf(stderr, "InnoDB: vtq_query_trx_id: get VTQ field failed: %s\n", err); + ut_ad(false && "get VTQ field failed"); + goto not_found; + } + } + + if (cached.trx_id != in_trx_id) + goto not_found; + + innobase_vtq_result(thd, cached, out, field); + found = true; + +not_found: + btr_pcur_close(&pcur); + mtr_commit(&mtr); + mem_heap_free(heap); + + DBUG_RETURN(found); +} + +static +inline +trx_id_t rec_get_trx_id(const rec_t* rec, ulint nfield) +{ + ulint len; + const byte* field; + field = rec_get_nth_field_old( + rec, nfield, &len); + + ut_ad(len == sizeof(trx_id_t)); + return mach_read_from_8(field); +} + +static +inline +void rec_get_timeval(const rec_t* rec, ulint nfield, timeval& out) +{ + ulint len; + const byte* field; + field = rec_get_nth_field_old( + rec, nfield, &len); + + ut_ad(len == sizeof(ullong)); + + out.tv_sec = mach_read_from_4(field); + out.tv_usec = mach_read_from_4(field + 4); +} + +inline +const char * +vtq_query_t::cache_result( + mem_heap_t* heap, + const rec_t* rec, + const timeval& _ts_query, + bool _backwards) +{ + prev_query = _ts_query; + backwards = _backwards; + return dict_process_sys_vtq(heap, rec, result); +} + +static +inline +bool +operator== (const timeval &a, const timeval &b) +{ + return a.tv_sec == b.tv_sec && a.tv_usec == b.tv_usec; +} + +static +inline +bool +operator> (const timeval &a, const timeval &b) +{ + return a.tv_sec > b.tv_sec || (a.tv_sec == b.tv_sec && a.tv_usec > b.tv_usec); +} + +static +inline +bool +operator< (const timeval &a, const timeval &b) +{ + return b > a; +} + +UNIV_INTERN +bool +vtq_query_commit_ts(THD* thd, void *out, const MYSQL_TIME &_commit_ts, vtq_field_t field, bool backwards) +{ + trx_t* trx; + btr_pcur_t pcur; + dtuple_t* tuple; + page_cur_mode_t mode; + mtr_t mtr; + mem_heap_t* heap; + uint err; + timeval commit_ts; + timeval rec_ts = { 0, 0 }; + const rec_t *rec, *clust_rec; + dict_index_t* index = dict_sys->vtq_commit_ts_ind; + dict_index_t* clust_index; + bool found = false; - result_net = rec_get_nth_field_old(rec, DICT_FLD__SYS_VTQ__BEGIN_TS, &len); - ut_ad(len == 8); - q->begin_ts.tv_sec = mach_read_from_4(result_net); - q->begin_ts.tv_usec = mach_read_from_4(result_net + 4); + DBUG_ENTER("vtq_query_commit_ts"); + + mode = backwards ? PAGE_CUR_LE : PAGE_CUR_GE; + + trx = thd_to_trx(thd); + ut_a(trx); + + vtq_record_t &cached = trx->vtq_query.result; + timeval &prev_query = trx->vtq_query.prev_query; + bool prev_bwds = trx->vtq_query.backwards; + + commit_ts.tv_usec = _commit_ts.second_part; + commit_ts.tv_sec = thd_get_timezone(thd)->TIME_to_gmt_sec(&_commit_ts, &err); + if (err) { + if (err == ER_WARN_DATA_OUT_OF_RANGE) { + if (_commit_ts.year <= TIMESTAMP_MIN_YEAR) { + commit_ts.tv_usec = 0; + commit_ts.tv_sec = 1; + } else { + ut_ad(_commit_ts.year >= TIMESTAMP_MAX_YEAR); + commit_ts.tv_usec = TIME_MAX_SECOND_PART; + commit_ts.tv_sec = MY_TIME_T_MAX; + } + } else { + DBUG_RETURN(false); + } + } else if (cached.commit_ts == commit_ts || + (prev_query.tv_sec && prev_bwds == backwards && ( + (!backwards && (commit_ts < prev_query) && commit_ts > cached.commit_ts) || + (backwards && (commit_ts > prev_query) && commit_ts < cached.commit_ts)))) + { + innobase_vtq_result(thd, cached, out, field); + DBUG_RETURN(true); + } + + heap = mem_heap_create(0); + + tuple = dtuple_create(heap, 1); + dict_index_copy_types(tuple, index, 1); + dtuple_get_nth_field(tuple, 0)->len = UNIV_SQL_NULL; + set_tuple_col_8(tuple, 0, commit_ts, heap); + + mtr_start_trx(&mtr, trx); + btr_pcur_open_on_user_rec(index, tuple, mode, + BTR_SEARCH_LEAF, &pcur, &mtr); - result_net = rec_get_nth_field_old(rec, DICT_FLD__SYS_VTQ__COMMIT_TS, &len); - ut_ad(len == 8); - q->commit_ts.tv_sec = mach_read_from_4(result_net); - q->commit_ts.tv_usec = mach_read_from_4(result_net + 4); + if (btr_pcur_is_on_user_rec(&pcur)) { + rec = btr_pcur_get_rec(&pcur); + rec_get_timeval(rec, 0, rec_ts); - if (q->trx_id != in_trx_id) + if (rec_ts.tv_sec == commit_ts.tv_sec + && rec_ts.tv_usec == commit_ts.tv_usec) + goto found; + } else { + rec_ts = commit_ts; + } + + if (mode == PAGE_CUR_GE) { + btr_pcur_move_to_prev_user_rec(&pcur, &mtr); + } else { + btr_pcur_move_to_next_user_rec(&pcur, &mtr); + } + + if (!btr_pcur_is_on_user_rec(&pcur)) goto not_found; - innobase_get_vtq_ts_result(thd, q, out, field); + rec = btr_pcur_get_rec(&pcur); +found: + clust_rec = row_get_clust_rec(BTR_SEARCH_LEAF, rec, index, &clust_index, &mtr); + if (!clust_rec) { + fprintf(stderr, "InnoDB: vtq_query_commit_ts: secondary index is out of sync\n"); + ut_ad(false && "secondary index is out of sync"); + goto not_found; + } + + { + const char *err = + trx->vtq_query.cache_result( + heap, + clust_rec, + rec_ts, + backwards); + if (err) { + fprintf(stderr, "InnoDB: vtq_query_commit_ts: get VTQ field failed: %s\n", err); + ut_ad(false && "get VTQ field failed"); + goto not_found; + } + } + innobase_vtq_result(thd, cached, out, field); found = true; not_found: @@ -23239,3 +23459,58 @@ innobase_get_vtq_ts(THD* thd, MYSQL_TIME *out, ulonglong _in_trx_id, vtq_field_t DBUG_RETURN(found); } + +bool +vtq_trx_sees( + THD *thd, + bool &result, + ulonglong trx_id1, + ulonglong trx_id0, + ulonglong commit_id1, + uchar iso_level1, + ulonglong commit_id0) +{ + DBUG_ENTER("vtq_trx_sees"); + + if (trx_id1 == trx_id0) { + result = false; + DBUG_RETURN(true); + } + + if (trx_id1 == ULONGLONG_MAX || trx_id0 == 0) { + result = true; + DBUG_RETURN(true); + } + + static const char* msg_cant_find = "InnoDB: vtq_trx_sees: can't find COMMIT_ID%c by TRX_ID: %llu\n"; + if (!commit_id1) { + if (!vtq_query_trx_id(thd, NULL, trx_id1, VTQ_ALL)) { + fprintf(stderr, msg_cant_find, '1', trx_id1); + DBUG_RETURN(false); + } + trx_t* trx = thd_to_trx(thd); + ut_ad(trx); + commit_id1 = trx->vtq_query.result.commit_id; + iso_level1 = trx->vtq_query.result.iso_level; + } + + if (!commit_id0) { + if (!vtq_query_trx_id(thd, &commit_id0, trx_id0, VTQ_COMMIT_ID)) { + fprintf(stderr, msg_cant_find, '0', trx_id0); + DBUG_RETURN(false); + } + } + + // Trivial case: TX1 started after TX0 committed + if (trx_id1 > commit_id0 + // Concurrent transactions: TX1 committed after TX0 and TX1 is read (un)committed + || (commit_id1 > commit_id0 && iso_level1 < TRX_ISO_REPEATABLE_READ)) + { + result = true; + } else { + // All other cases: TX1 does not see TX0 + result = false; + } + + DBUG_RETURN(true); +} diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index d3f3cff82f897..436cea7fe4b8d 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -9669,7 +9669,16 @@ static ST_FIELD_INFO innodb_vtq_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE) }, -#define SYS_VTQ_BEGIN_TS 1 +#define SYS_VTQ_COMMIT_ID 1 + { STRUCT_FLD(field_name, "commit_id"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE) }, + +#define SYS_VTQ_BEGIN_TS 2 { STRUCT_FLD(field_name, "begin_ts"), STRUCT_FLD(field_length, 6), STRUCT_FLD(field_type, MYSQL_TYPE_TIMESTAMP), @@ -9678,7 +9687,7 @@ static ST_FIELD_INFO innodb_vtq_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE) }, -#define SYS_VTQ_COMMIT_TS 2 +#define SYS_VTQ_COMMIT_TS 3 { STRUCT_FLD(field_name, "commit_ts"), STRUCT_FLD(field_length, 6), STRUCT_FLD(field_type, MYSQL_TYPE_TIMESTAMP), @@ -9687,13 +9696,12 @@ static ST_FIELD_INFO innodb_vtq_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE) }, -#define SYS_VTQ_CONCURR_TRX 3 - { STRUCT_FLD(field_name, "concurr_trx"), - // 3 for "..." if list is truncated - STRUCT_FLD(field_length, I_S_MAX_CONCURR_TRX * (TRX_ID_MAX_LEN + 1) + 3), +#define SYS_VTQ_ISO_LEVEL 4 + { STRUCT_FLD(field_name, "iso_level"), + STRUCT_FLD(field_length, 2), STRUCT_FLD(field_type, MYSQL_TYPE_STRING), STRUCT_FLD(value, 0), - STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(field_flags, 0), STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE) }, @@ -9709,21 +9717,35 @@ int i_s_dict_fill_vtq( /*========================*/ THD* thd, /*!< in: thread */ - ullong col_trx_id, /*!< in: table fields */ - timeval& col_begin_ts, - timeval& col_commit_ts, - char* col_concurr_trx, + vtq_record_t& vtq, /*!< in: table fields */ TABLE* table_to_fill) /*!< in/out: fill this table */ { Field** fields; + const char* iso_level; DBUG_ENTER("i_s_dict_fill_vtq"); fields = table_to_fill->field; - OK(field_store_ullong(fields[SYS_VTQ_TRX_ID], col_trx_id)); - OK(field_store_timeval(fields[SYS_VTQ_BEGIN_TS], col_begin_ts, thd)); - OK(field_store_timeval(fields[SYS_VTQ_COMMIT_TS], col_commit_ts, thd)); - OK(field_store_string(fields[SYS_VTQ_CONCURR_TRX], col_concurr_trx)); + switch (vtq.iso_level) { + case TRX_ISO_REPEATABLE_READ: + iso_level = "RR"; + break; + case TRX_ISO_READ_COMMITTED: + iso_level = "RC"; + break; + case TRX_ISO_SERIALIZABLE: + iso_level = "S"; + break; + case TRX_ISO_READ_UNCOMMITTED: + iso_level = "RU"; + break; + } + + OK(field_store_ullong(fields[SYS_VTQ_TRX_ID], vtq.trx_id)); + OK(field_store_ullong(fields[SYS_VTQ_COMMIT_ID], vtq.commit_id)); + OK(field_store_timeval(fields[SYS_VTQ_BEGIN_TS], vtq.begin_ts, thd)); + OK(field_store_timeval(fields[SYS_VTQ_COMMIT_TS], vtq.commit_ts, thd)); + OK(field_store_string(fields[SYS_VTQ_ISO_LEVEL], iso_level)); OK(schema_table_store_record(thd, table_to_fill)); @@ -9768,19 +9790,13 @@ i_s_sys_vtq_fill_table( for (int i = 0; rec && i < I_S_SYS_VTQ_LIMIT; ++i) { const char* err_msg; - trx_id_t col_trx_id; - timeval col_begin_ts; - timeval col_commit_ts; - char* col_concurr_trx; + vtq_record_t fields; /* Extract necessary information from SYS_VTQ row */ err_msg = dict_process_sys_vtq( heap, rec, - &col_trx_id, - &col_begin_ts, - &col_commit_ts, - &col_concurr_trx); + fields); mtr_commit(&mtr); mutex_exit(&dict_sys->mutex); @@ -9788,10 +9804,7 @@ i_s_sys_vtq_fill_table( if (!err_msg) { err = i_s_dict_fill_vtq( thd, - col_trx_id, - col_begin_ts, - col_commit_ts, - col_concurr_trx, + fields, tables->table); } else { push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, diff --git a/storage/innobase/include/dict0boot.h b/storage/innobase/include/dict0boot.h index 22b0489386d4c..bc9fed90f6854 100644 --- a/storage/innobase/include/dict0boot.h +++ b/storage/innobase/include/dict0boot.h @@ -325,11 +325,16 @@ enum dict_fld_sys_datafiles_enum { DICT_FLD__SYS_DATAFILES__PATH = 3, DICT_NUM_FIELDS__SYS_DATAFILES = 4 }; + /* The columns in SYS_VTQ */ enum dict_col_sys_vtq_enum { DICT_COL__SYS_VTQ__TRX_ID = 0, - DICT_NUM_COLS__SYS_VTQ = 1 + DICT_COL__SYS_VTQ__COMMIT_ID = 1, + DICT_COL__SYS_VTQ__BEGIN_TS = 2, + DICT_COL__SYS_VTQ__COMMIT_TS = 3, + DICT_COL__SYS_VTQ__ISOLATION_LEVEL = 4, + DICT_NUM_COLS__SYS_VTQ = 5 }; /* The field numbers in the SYS_VTQ clustered index */ enum dict_fld_sys_vtq_enum @@ -337,10 +342,11 @@ enum dict_fld_sys_vtq_enum DICT_FLD__SYS_VTQ__TRX_ID = 0, DICT_FLD__SYS_VTQ__DB_TRX_ID = 1, DICT_FLD__SYS_VTQ__DB_ROLL_PTR = 2, - DICT_FLD__SYS_VTQ__BEGIN_TS = 3, - DICT_FLD__SYS_VTQ__COMMIT_TS = 4, - DICT_FLD__SYS_VTQ__CONCURR_TRX = 5, - DICT_NUM_FIELDS__SYS_VTQ = 6 + DICT_FLD__SYS_VTQ__COMMIT_ID = 3, + DICT_FLD__SYS_VTQ__BEGIN_TS = 4, + DICT_FLD__SYS_VTQ__COMMIT_TS = 5, + DICT_FLD__SYS_VTQ__ISOLATION_LEVEL = 6, + DICT_NUM_FIELDS__SYS_VTQ = 7 }; /* The columns in SYS_VIRTUAL */ diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 56ca8325d4518..6e79c2e4b8b78 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -1737,8 +1737,9 @@ struct dict_sys_t{ dict_table_t* sys_columns; /*!< SYS_COLUMNS table */ dict_table_t* sys_indexes; /*!< SYS_INDEXES table */ dict_table_t* sys_fields; /*!< SYS_FIELDS table */ - dict_table_t* sys_virtual; /*!< SYS_VIRTUAL table */ dict_table_t* sys_vtq; /*!< SYS_VTQ table */ + dict_index_t* vtq_commit_ts_ind; + dict_table_t* sys_virtual; /*!< SYS_VIRTUAL table */ /*=============================*/ UT_LIST_BASE_NODE_T(dict_table_t) diff --git a/storage/innobase/include/dict0load.h b/storage/innobase/include/dict0load.h index d9533240c18fc..a6a69d9aafbe8 100644 --- a/storage/innobase/include/dict0load.h +++ b/storage/innobase/include/dict0load.h @@ -31,6 +31,7 @@ Created 4/24/1996 Heikki Tuuri #include "univ.i" #include "dict0types.h" #include "trx0types.h" +#include "trx0vtq.h" #include "ut0byte.h" #include "mem0mem.h" #include "btr0types.h" @@ -320,17 +321,14 @@ dict_process_sys_datafiles( This function parses a SYS_VTQ record, extracts necessary information from the record and returns it to the caller. @return error message, or NULL on success */ -#define I_S_MAX_CONCURR_TRX 100 UNIV_INTERN const char* dict_process_sys_vtq( /*=======================*/ mem_heap_t* heap, /*!< in/out: heap memory */ const rec_t* rec, /*!< in: current rec */ -ullong* col_trx_id, /*!< out: field values */ -timeval* col_begin_ts, -timeval* col_commit_ts, -char** col_concurr_trx); +vtq_record_t& fields /*!< out: field values */ +); /** Update the record for space_id in SYS_TABLESPACES to this filepath. @param[in] space_id Tablespace ID diff --git a/storage/innobase/include/row0ins.ic b/storage/innobase/include/row0ins.ic index 7b91e8b3cacea..9f951bda2be05 100644 --- a/storage/innobase/include/row0ins.ic +++ b/storage/innobase/include/row0ins.ic @@ -25,35 +25,54 @@ Created 4/20/1996 Heikki Tuuri UNIV_INLINE -void set_row_field_8( - dtuple_t* row, - int field_num, +void set_tuple_col_8( + dtuple_t* tuple, + int col, ib_uint64_t data, mem_heap_t* heap) { static const ulint fsize = sizeof(data); - dfield_t* dfield = dtuple_get_nth_field(row, field_num); + dfield_t* dfield = dtuple_get_nth_field(tuple, col); ut_ad(dfield->type.len == fsize); if (dfield->len == UNIV_SQL_NULL) { byte* buf = reinterpret_cast(mem_heap_alloc(heap, fsize)); dfield_set_data(dfield, buf, fsize); } + ut_ad(dfield->len == dfield->type.len && dfield->data); mach_write_to_8(dfield->data, data); } UNIV_INLINE -void set_row_field_8( - dtuple_t* row, - int field_num, +void set_tuple_col_8( + dtuple_t* tuple, + int col, timeval& data, mem_heap_t* heap) { - dfield_t* dfield = dtuple_get_nth_field(row, field_num); + dfield_t* dfield = dtuple_get_nth_field(tuple, col); ut_ad(dfield->type.len == 8); if (dfield->len == UNIV_SQL_NULL) { byte* buf = reinterpret_cast(mem_heap_alloc(heap, 8)); dfield_set_data(dfield, buf, 8); } + ut_ad(dfield->len == dfield->type.len && dfield->data); mach_write_to_4(reinterpret_cast(dfield->data), (ulint) data.tv_sec); mach_write_to_4(reinterpret_cast(dfield->data) + 4, (ulint) data.tv_usec); } + +UNIV_INLINE +void set_tuple_col_1( + dtuple_t* tuple, + int col, + byte data, + mem_heap_t* heap) +{ + dfield_t* dfield = dtuple_get_nth_field(tuple, col); + ut_ad(dfield->type.len == 1); + if (dfield->len == UNIV_SQL_NULL) { + byte* buf = reinterpret_cast(mem_heap_alloc(heap, 1)); + dfield_set_data(dfield, buf, 1); + } + ut_ad(dfield->len == dfield->type.len && dfield->data); + *(byte*)(dfield->data) = data; +} diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 995929b957c6b..dd8d1bd524c7c 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -42,6 +42,7 @@ Created 3/26/1996 Heikki Tuuri #include "que0types.h" #include "mem0mem.h" #include "trx0xa.h" +#include "trx0vtq.h" #include "ut0vec.h" #include "fts0fts.h" #include "srv0srv.h" @@ -829,13 +830,6 @@ typedef enum { TRX_WSREP_ABORT = 1 } trx_abort_t; -struct vtq_query_t -{ - trx_id_t trx_id; - timeval begin_ts; - timeval commit_ts; -}; - /** Represents an instance of rollback segment along with its state variables.*/ struct trx_undo_ptr_t { trx_rseg_t* rseg; /*!< rollback segment assigned to the @@ -1277,8 +1271,6 @@ struct trx_t { bool vtq_notify_on_commit; /*!< Notify VTQ for System Versioned update */ vtq_query_t vtq_query; - trx_id_t* vtq_concurr_trx; - ulint vtq_concurr_n; ulint magic_n; /** @return whether any persistent undo log has been generated */ diff --git a/storage/innobase/include/trx0vtq.h b/storage/innobase/include/trx0vtq.h new file mode 100644 index 0000000000000..5767dfeb5a0c3 --- /dev/null +++ b/storage/innobase/include/trx0vtq.h @@ -0,0 +1,40 @@ +#ifndef trx0vtq_h +#define trx0vtq_h + +/* Copyright (c) 2016, MariaDB Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +#include +#include "trx0types.h" +#include "mem0mem.h" +#include "rem0types.h" + +class vtq_query_t +{ +public: + timeval prev_query; + bool backwards; + + vtq_record_t result; + + const char * cache_result(mem_heap_t* heap, const rec_t* rec); + const char * cache_result( + mem_heap_t* heap, + const rec_t* rec, + const timeval &_ts_query, + bool _backwards); +}; + +#endif // trx0vtq_h diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index ef30a434bf636..40d3eccdc346d 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -3905,7 +3905,7 @@ Inserts a row to SYS_VTQ, low level. code */ static __attribute__((nonnull, warn_unused_result)) dberr_t -vers_row_ins_vtq_low(trx_t* trx, mem_heap_t* heap, dtuple_t* row) +vers_row_ins_vtq_low(trx_t* trx, mem_heap_t* heap, dtuple_t* tuple) { dberr_t err; dtuple_t* entry; @@ -3916,7 +3916,7 @@ vers_row_ins_vtq_low(trx_t* trx, mem_heap_t* heap, dtuple_t* row) | BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG); - entry = row_build_index_entry(row, NULL, index, heap); + entry = row_build_index_entry(tuple, NULL, index, heap); dfield_t* dfield = dtuple_get_nth_field(entry, DATA_TRX_ID); ut_ad(dfield->type.len == DATA_TRX_ID_LEN); @@ -3946,12 +3946,12 @@ vers_row_ins_vtq_low(trx_t* trx, mem_heap_t* heap, dtuple_t* row) n_index++; - entry = row_build_index_entry(row, NULL, index, heap); + entry = row_build_index_entry(tuple, NULL, index, heap); err = row_ins_sec_index_entry_low( flags, BTR_MODIFY_TREE, index, offsets_heap, heap, entry, trx->id, NULL, false, trx); } while (err == DB_SUCCESS); - ut_ad(n_index == 2 || err != DB_SUCCESS); + ut_ad(n_index == 3 || err != DB_SUCCESS); mem_heap_free(offsets_heap); return err; @@ -3964,31 +3964,26 @@ void vers_notify_vtq(trx_t* trx) { dberr_t err; mem_heap_t* heap = mem_heap_create(1024); - dtuple_t* row = dtuple_create(heap, dict_table_get_n_cols(dict_sys->sys_vtq)); + dtuple_t* tuple = dtuple_create(heap, dict_table_get_n_cols(dict_sys->sys_vtq)); timeval begin_ts, commit_ts; begin_ts.tv_sec = trx->start_time; begin_ts.tv_usec = trx->start_time_micro; - ut_usectime((ulong*)&commit_ts.tv_sec, (ulong*)&commit_ts.tv_usec); - dict_table_copy_types(row, dict_sys->sys_vtq); - set_row_field_8(row, DICT_FLD__SYS_VTQ__TRX_ID, trx->id, heap); - set_row_field_8(row, DICT_FLD__SYS_VTQ__BEGIN_TS - 2, begin_ts, heap); - set_row_field_8(row, DICT_FLD__SYS_VTQ__COMMIT_TS - 2, commit_ts, heap); + mutex_enter(&trx_sys->mutex); + trx_id_t commit_id = trx_sys_get_new_trx_id(); + ut_usectime((ulint *)&commit_ts.tv_sec, (ulint *)&commit_ts.tv_usec); + mutex_exit(&trx_sys->mutex); - dfield_t* dfield = dtuple_get_nth_field(row, DICT_FLD__SYS_VTQ__CONCURR_TRX - 2); - ulint count = 0; - byte* buf = NULL; - if (trx->vtq_concurr_n > 0) { - buf = static_cast(mem_heap_alloc(heap, trx->vtq_concurr_n * 8)); - for (byte* ptr = buf; count < trx->vtq_concurr_n; ++count) { - mach_write_to_8(ptr, trx->vtq_concurr_trx[count]); - ptr += 8; - } - } - dfield_set_data(dfield, buf, count * 8); + dict_table_copy_types(tuple, dict_sys->sys_vtq); + set_tuple_col_8(tuple, DICT_COL__SYS_VTQ__TRX_ID, trx->id, heap); + set_tuple_col_8(tuple, DICT_COL__SYS_VTQ__COMMIT_ID, commit_id, heap); + set_tuple_col_8(tuple, DICT_COL__SYS_VTQ__BEGIN_TS, begin_ts, heap); + set_tuple_col_8(tuple, DICT_COL__SYS_VTQ__COMMIT_TS, commit_ts, heap); + ut_ad(trx->isolation_level < 256); + set_tuple_col_1(tuple, DICT_COL__SYS_VTQ__ISOLATION_LEVEL, trx->isolation_level, heap); - err = vers_row_ins_vtq_low(trx, heap, row); + err = vers_row_ins_vtq_low(trx, heap, tuple); if (DB_SUCCESS != err) fprintf(stderr, "InnoDB: failed to insert VTQ record (error %d)\n", err); diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 60b221a4e4acf..5edf3c1af54d4 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -1495,15 +1495,15 @@ row_insert_for_mysql( ut_ad(t->mysql_col_len == 8); if (historical) { - set_row_field_8(node->row, table->vers_row_end, trx->id, node->entry_sys_heap); + set_tuple_col_8(node->row, table->vers_row_end, trx->id, node->entry_sys_heap); int8store(&mysql_rec[t->mysql_col_offset], trx->id); } else { - set_row_field_8(node->row, table->vers_row_end, IB_UINT64_MAX, node->entry_sys_heap); + set_tuple_col_8(node->row, table->vers_row_end, IB_UINT64_MAX, node->entry_sys_heap); int8store(&mysql_rec[t->mysql_col_offset], IB_UINT64_MAX); t = &prebuilt->mysql_template[table->vers_row_start]; ut_ad(t->mysql_col_len == 8); - set_row_field_8(node->row, table->vers_row_start, trx->id, node->entry_sys_heap); + set_tuple_col_8(node->row, table->vers_row_start, trx->id, node->entry_sys_heap); int8store(&mysql_rec[t->mysql_col_offset], trx->id); } } diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 7e1666c1703f7..7298fc62b4c9a 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -316,10 +316,6 @@ struct TrxFactory { trx->lock.table_locks.~lock_pool_t(); trx->hit_list.~hit_list_t(); - - if (trx->vtq_concurr_trx) { - ut_free(trx->vtq_concurr_trx); - } } /** Enforce any invariants here, this is called before the transaction @@ -1332,13 +1328,6 @@ trx_start_low( || srv_read_only_mode || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO); - if (UT_LIST_GET_LEN(trx_sys->rw_trx_list) > 0) { - trx->vtq_concurr_trx = static_cast( - ut_malloc_nokey(UT_LIST_GET_LEN(trx_sys->rw_trx_list) * sizeof(trx_id_t))); - copy_trx_ids f(trx->vtq_concurr_trx, trx->vtq_concurr_n); - ut_list_map(trx_sys->rw_trx_list, f); - } - UT_LIST_ADD_FIRST(trx_sys->rw_trx_list, trx); ut_d(trx->in_rw_trx_list = true);