mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
IB, SQL: (0.4) COMMIT_ID-based ordering of transactions
IB: * removed CONCURR_TRX from VTQ; * new fields in VTQ: COMMIT_ID, ISO_LEVEL. SQL: * renamed BEGIN_TS, COMMIT_TS to VTQ_BEGIN_TS, VTQ_COMMIT_TS; * new functions: VTQ_COMMIT_ID, VTQ_ISO_LEVEL, VTQ_TRX_ID, VTQ_TRX_SEES, VTQ_TRX_SEES_EQ; * versioned SELECT for IB uses VTQ_TRX_SEES, VTQ_TRX_SEES_EQ. Closes #71
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
103
mysql-test/suite/versioning/r/commit_id.result
Normal file
103
mysql-test/suite/versioning/r/commit_id.result
Normal file
@@ -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;
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
79
mysql-test/suite/versioning/t/commit_id.test
Normal file
79
mysql-test/suite/versioning/t/commit_id.test
Normal file
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
||||
13
sql/item.h
13
sql/item.h
@@ -480,9 +480,20 @@ public:
|
||||
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 &);
|
||||
/**
|
||||
|
||||
@@ -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 <vtq_field_t VTQ_FIELD>
|
||||
class Create_func_vtq : public Create_native_func
|
||||
{
|
||||
public:
|
||||
virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
|
||||
|
||||
static Create_func_begin_ts s_singleton;
|
||||
static Create_func_vtq<VTQ_FIELD> s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_begin_ts() {}
|
||||
virtual ~Create_func_begin_ts() {}
|
||||
Create_func_vtq<VTQ_FIELD>() {}
|
||||
virtual ~Create_func_vtq<VTQ_FIELD>() {}
|
||||
};
|
||||
|
||||
Create_func_begin_ts Create_func_begin_ts::s_singleton;
|
||||
template<vtq_field_t VTQ_FIELD>
|
||||
Create_func_vtq<VTQ_FIELD> Create_func_vtq<VTQ_FIELD>::s_singleton;
|
||||
|
||||
template <vtq_field_t VTQ_FIELD>
|
||||
Item*
|
||||
Create_func_begin_ts::create_native(THD *thd, LEX_STRING name,
|
||||
Create_func_vtq<VTQ_FIELD>::create_native(THD *thd, LEX_STRING name,
|
||||
List<Item> *item_list)
|
||||
{
|
||||
Item *func= NULL;
|
||||
@@ -6708,50 +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;
|
||||
}
|
||||
default:
|
||||
{
|
||||
my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return func;
|
||||
}
|
||||
|
||||
class Create_func_commit_ts : public Create_native_func
|
||||
{
|
||||
public:
|
||||
virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *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;
|
||||
|
||||
Item*
|
||||
Create_func_commit_ts::create_native(THD *thd, LEX_STRING name,
|
||||
List<Item> *item_list)
|
||||
{
|
||||
Item *func= NULL;
|
||||
int arg_count= 0;
|
||||
|
||||
if (item_list != NULL)
|
||||
arg_count= item_list->elements;
|
||||
|
||||
switch (arg_count) {
|
||||
case 1:
|
||||
case 2:
|
||||
{
|
||||
Item *param_1= item_list->pop();
|
||||
func= new (thd->mem_root) Item_func_vtq_ts(thd, param_1, VTQ_COMMIT_TS);
|
||||
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);
|
||||
@@ -6760,8 +6750,45 @@ Create_func_commit_ts::create_native(THD *thd, LEX_STRING name,
|
||||
}
|
||||
|
||||
return func;
|
||||
}
|
||||
};
|
||||
|
||||
template <class Item_func_vtq_trx_seesX>
|
||||
class Create_func_vtq_trx_sees : public Create_native_func
|
||||
{
|
||||
public:
|
||||
virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list)
|
||||
{
|
||||
Item *func= NULL;
|
||||
int arg_count= 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return func;
|
||||
}
|
||||
|
||||
static Create_func_vtq_trx_sees<Item_func_vtq_trx_seesX> s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_vtq_trx_sees<Item_func_vtq_trx_seesX>() {}
|
||||
virtual ~Create_func_vtq_trx_sees<Item_func_vtq_trx_seesX>() {}
|
||||
};
|
||||
|
||||
template<class X>
|
||||
Create_func_vtq_trx_sees<X> Create_func_vtq_trx_sees<X>::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<VTQ_BEGIN_TS>)},
|
||||
{ { C_STRING_WITH_LEN("VTQ_COMMIT_ID") }, BUILDER(Create_func_vtq<VTQ_COMMIT_ID>)},
|
||||
{ { C_STRING_WITH_LEN("VTQ_COMMIT_TS") }, BUILDER(Create_func_vtq<VTQ_COMMIT_TS>)},
|
||||
{ { C_STRING_WITH_LEN("VTQ_ISO_LEVEL") }, BUILDER(Create_func_vtq<VTQ_ISO_LEVEL>)},
|
||||
{ { C_STRING_WITH_LEN("VTQ_TRX_ID") }, BUILDER(Create_func_vtq<VTQ_TRX_ID>)},
|
||||
{ { C_STRING_WITH_LEN("VTQ_TRX_SEES") }, BUILDER(Create_func_vtq_trx_sees<Item_func_vtq_trx_sees>)},
|
||||
{ { C_STRING_WITH_LEN("VTQ_TRX_SEES_EQ") }, BUILDER(Create_func_vtq_trx_sees<Item_func_vtq_trx_sees_eq>)},
|
||||
{ { 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)},
|
||||
|
||||
@@ -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<Item_datetimefunc>(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<Item_datetimefunc>(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 <class Item_func_X>
|
||||
void
|
||||
VTQ_common<Item_func_X>::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<Item_field *>(args[0]);
|
||||
static_cast<Item_field *>(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<Item_int_func>(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<Item_int_func>(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<Item_bool_func>(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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1288,10 +1288,28 @@ public:
|
||||
|
||||
#include "vtq.h"
|
||||
|
||||
class Item_func_vtq_ts :public Item_datetimefunc
|
||||
template <class Item_func_X>
|
||||
class VTQ_common : public Item_func_X
|
||||
{
|
||||
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<Item_datetimefunc>
|
||||
{
|
||||
vtq_field_t vtq_field;
|
||||
handlerton *hton;
|
||||
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 @@ public:
|
||||
{
|
||||
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<Item_func_vtq_ts>(thd, mem_root, this); }
|
||||
};
|
||||
|
||||
class Item_func_vtq_id :
|
||||
public VTQ_common<Item_int_func>
|
||||
{
|
||||
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<Item_func_vtq_id>(thd, mem_root, this); }
|
||||
};
|
||||
|
||||
class Item_func_vtq_trx_sees :
|
||||
public VTQ_common<Item_bool_func>
|
||||
{
|
||||
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<Item_func_vtq_trx_sees>(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 */
|
||||
|
||||
@@ -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= 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);
|
||||
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:
|
||||
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
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
18
sql/vtq.h
18
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
|
||||
};
|
||||
|
||||
struct vtq_record_t
|
||||
{
|
||||
ulonglong trx_id;
|
||||
ulonglong commit_id;
|
||||
timeval begin_ts;
|
||||
timeval commit_ts;
|
||||
uchar iso_level;
|
||||
};
|
||||
|
||||
#endif /* VTQ_INCLUDED */
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<char*>(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);
|
||||
}
|
||||
|
||||
@@ -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<vtq_record_t *>(out) = q;
|
||||
}
|
||||
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_TRX_ID:
|
||||
*reinterpret_cast<trx_id_t *>(out) = q.trx_id;
|
||||
break;
|
||||
case VTQ_COMMIT_ID:
|
||||
*reinterpret_cast<trx_id_t *>(out) = q.commit_id;
|
||||
break;
|
||||
case VTQ_BEGIN_TS: {
|
||||
MYSQL_TIME* out_ts = reinterpret_cast<MYSQL_TIME *>(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<MYSQL_TIME *>(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<uint *>(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,19 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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 (q->trx_id != in_trx_id)
|
||||
if (cached.trx_id != in_trx_id)
|
||||
goto not_found;
|
||||
|
||||
innobase_get_vtq_ts_result(thd, q, out, field);
|
||||
innobase_vtq_result(thd, cached, out, field);
|
||||
found = true;
|
||||
|
||||
not_found:
|
||||
@@ -23239,3 +23277,240 @@ not_found:
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
if (btr_pcur_is_on_user_rec(&pcur)) {
|
||||
rec = btr_pcur_get_rec(&pcur);
|
||||
rec_get_timeval(rec, 0, rec_ts);
|
||||
|
||||
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;
|
||||
|
||||
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:
|
||||
btr_pcur_close(&pcur);
|
||||
mtr_commit(&mtr);
|
||||
mem_heap_free(heap);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<byte*>(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<byte*>(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<byte*>(dfield->data), (ulint) data.tv_sec);
|
||||
mach_write_to_4(reinterpret_cast<byte*>(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<byte*>(mem_heap_alloc(heap, 1));
|
||||
dfield_set_data(dfield, buf, 1);
|
||||
}
|
||||
ut_ad(dfield->len == dfield->type.len && dfield->data);
|
||||
*(byte*)(dfield->data) = data;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
40
storage/innobase/include/trx0vtq.h
Normal file
40
storage/innobase/include/trx0vtq.h
Normal file
@@ -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 <vtq.h>
|
||||
#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
|
||||
@@ -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<byte*>(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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<trx_id_t *>(
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user