1
0
mirror of https://github.com/MariaDB/server.git synced 2025-12-24 11:21:21 +03:00

Merge 10.1 to 10.2

Most conflicts are related to the MDEV-11638 InnoDB shutdown refactoring.
This commit is contained in:
Marko Mäkelä
2017-01-05 10:48:03 +02:00
74 changed files with 980 additions and 4322 deletions

View File

@@ -5786,6 +5786,7 @@ void do_connect(struct st_command *command)
my_bool con_shm __attribute__ ((unused))= 0;
int read_timeout= 0;
int write_timeout= 0;
int connect_timeout= 0;
struct st_connection* con_slot;
static DYNAMIC_STRING ds_connection_name;
@@ -5892,6 +5893,11 @@ void do_connect(struct st_command *command)
{
write_timeout= atoi(con_options + sizeof("write_timeout=")-1);
}
else if (strncasecmp(con_options, "connect_timeout=",
sizeof("connect_timeout=")-1) == 0)
{
connect_timeout= atoi(con_options + sizeof("connect_timeout=")-1);
}
else
die("Illegal option to connect: %.*s",
(int) (end - con_options), con_options);
@@ -5976,6 +5982,12 @@ void do_connect(struct st_command *command)
(char*)&write_timeout);
}
if (connect_timeout)
{
mysql_options(con_slot->mysql, MYSQL_OPT_CONNECT_TIMEOUT,
(char*)&connect_timeout);
}
#ifdef HAVE_SMEM
if (con_shm)
{

View File

@@ -82,8 +82,14 @@ perl;
}
$ENV{'SEARCH_FILE'} =~ s{^.*?([^/\\]+)$}{$1};
if ($content =~ m{$search_pattern}) {
die "FOUND /$search_pattern/ in $ENV{'SEARCH_FILE'}\n"
if $ENV{SEARCH_ABORT} eq 'FOUND';
print "FOUND /$search_pattern/ in $ENV{'SEARCH_FILE'}\n"
unless defined $ENV{SEARCH_ABORT};
} else {
die "NOT FOUND /$search_pattern/ in $ENV{'SEARCH_FILE'}\n"
if $ENV{SEARCH_ABORT} eq 'NOT FOUND';
print "NOT FOUND /$search_pattern/ in $ENV{'SEARCH_FILE'}\n"
unless defined $ENV{SEARCH_ABORT};
}
EOF

View File

@@ -2158,35 +2158,31 @@ Warning 1052 Column 'kundentyp' in group statement is ambiguous
drop table t1;
SET optimizer_switch=@save_optimizer_switch;
connection default;
SELECT sleep(5.5);
SELECT sleep(50);
connect con2,localhost,root,,;
connection con2;
SELECT sleep(5);
SELECT sleep(50);
# -- Success: more than --thread_pool_max_threads normal connections not possible
connection default;
sleep(5.5)
0
connection con2;
sleep(5)
0
connection default;
SELECT sleep(5);
connection con2;
SELECT sleep(5);
connect extracon,127.0.0.1,root,,test,$MASTER_EXTRA_PORT,;
connection extracon;
SELECT 'Connection on extra port ok';
Connection on extra port ok
Connection on extra port ok
SELECT sleep(5.5);
connect extracon2,127.0.0.1,root,,test,$MASTER_EXTRA_PORT,;
connection extracon2;
SELECT 'Connection on extra port 2 ok';
Connection on extra port 2 ok
Connection on extra port 2 ok
# -- Success: more than --extra-max-connections + 1 normal connections not possible
connection extracon2;
KILL QUERY <default_connection_ID>;
KILL QUERY <con2_connection_ID>;
connection default;
sleep(5)
0
sleep(50)
1
connection con2;
sleep(5)
sleep(50)
1
connection extracon;
sleep(5.5)
0

View File

@@ -10,7 +10,5 @@
#
##############################################################################
innodb_scrub : MDEV-8139
innodb_scrub_compressed : MDEV-8139
innodb_scrub_background : MDEV-8139
innodb_scrub_background : MDEV-8139 background scrubbing does not work reliably
innodb_scrub : MDEV-8139 occasional corruption of delete_3.ibd page 2

View File

@@ -1,207 +1,121 @@
create table snapshot_status engine = myisam
select * from information_schema.global_status
where variable_name like 'innodb_scrub%';
#
# Test delete of records
#
create table t1 (
where variable_name like 'innodb_scrub_background%';
# MDEV-8139 Fix scrubbing tests
# FIXME: Add index(b) to each table; ensure that undo logs are scrubbed.
create table delete_3 (
a int auto_increment primary key,
b varchar(256),
c text) engine = innodb row_format=compressed;
delete from delete_3;
create table delete_rollback_delete_3 (
a int auto_increment primary key,
b varchar(256),
c text) engine = innodb row_format=compressed;
begin;
delete from delete_rollback_delete_3;
rollback;
delete from delete_rollback_delete_3;
create table insert_rollback_3 (
a int auto_increment primary key,
b varchar(256),
c text) engine = innodb row_format=compressed;
begin;
rollback;
create table delete_2 (
a int auto_increment primary key,
b varchar(256),
c text) engine = innodb row_format=compact;
# Populate table with rows
delete from t1;
# restart mysqld so that all pages are flushed
# read all rows from table
select * from t1;
# compact: delete from: grep -c bicycle t1.ibd
0
# compact: delete from: grep -c bicycle ibdata1
0
# compact: delete from: grep -c repairman t1.ibd
0
# compact: delete from: grep -c repairman ibdata1
0
drop table t1;
#
# Test delete+rollback+delete
#
create table t1 (
delete from delete_2;
create table delete_rollback_delete_2 (
a int auto_increment primary key,
b varchar(256),
c text) engine = innodb row_format=compact;
# Populate table with rows
begin;
delete from t1;
delete from delete_rollback_delete_2;
rollback;
delete from t1;
# restart mysqld so that all pages are flushed
# read all rows from table
select * from t1;
# compact: delete rollback: grep -c bicycle t1.ibd
0
# compact: delete rollback: grep -c bicycle ibdata1
0
# compact: delete rollback: grep -c repairman t1.ibd
0
# compact: delete rollback: grep -c repairman ibdata1
0
drop table t1;
#
# Test insert+rollback
#
create table t1 (
delete from delete_rollback_delete_2;
create table insert_rollback_2 (
a int auto_increment primary key,
b varchar(256),
c text) engine = innodb row_format=compact;
# Populate table with rows
begin;
rollback;
# restart mysqld so that all pages are flushed
# read all rows from table
select * from t1;
# compact: insert rollback: grep -c bicycle t1.ibd
0
# compact: insert rollback: grep -c bicycle ibdata1
0
# compact: insert rollback: grep -c repairman t1.ibd
0
# compact: insert rollback: grep -c repairman ibdata1
0
drop table t1;
#
# Test delete of records
#
create table t1 (
create table delete_1 (
a int auto_increment primary key,
b varchar(256),
c text) engine = innodb row_format=redundant;
# Populate table with rows
delete from t1;
# restart mysqld so that all pages are flushed
# read all rows from table
select * from t1;
# redundant: delete from: grep -c bicycle t1.ibd
0
# redundant: delete from: grep -c bicycle ibdata1
0
# redundant: delete from: grep -c repairman t1.ibd
0
# redundant: delete from: grep -c repairman ibdata1
0
drop table t1;
#
# Test delete+rollback+delete
#
create table t1 (
delete from delete_1;
create table delete_rollback_delete_1 (
a int auto_increment primary key,
b varchar(256),
c text) engine = innodb row_format=redundant;
# Populate table with rows
begin;
delete from t1;
delete from delete_rollback_delete_1;
rollback;
delete from t1;
# restart mysqld so that all pages are flushed
# read all rows from table
select * from t1;
# redundant: delete rollback: grep -c bicycle t1.ibd
0
# redundant: delete rollback: grep -c bicycle ibdata1
0
# redundant: delete rollback: grep -c repairman t1.ibd
0
# redundant: delete rollback: grep -c repairman ibdata1
0
drop table t1;
#
# Test insert+rollback
#
create table t1 (
delete from delete_rollback_delete_1;
create table insert_rollback_1 (
a int auto_increment primary key,
b varchar(256),
c text) engine = innodb row_format=redundant;
# Populate table with rows
begin;
rollback;
# restart mysqld so that all pages are flushed
# read all rows from table
select * from t1;
# redundant: insert rollback: grep -c bicycle t1.ibd
0
# redundant: insert rollback: grep -c bicycle ibdata1
0
# redundant: insert rollback: grep -c repairman t1.ibd
0
# redundant: insert rollback: grep -c repairman ibdata1
0
drop table t1;
#
# Test delete of records
#
create table t1 (
create table delete_0 (
a int auto_increment primary key,
b varchar(256),
c text) engine = innodb row_format=dynamic;
# Populate table with rows
delete from t1;
# restart mysqld so that all pages are flushed
# read all rows from table
select * from t1;
# dynamic: delete from: grep -c bicycle t1.ibd
0
# dynamic: delete from: grep -c bicycle ibdata1
0
# dynamic: delete from: grep -c repairman t1.ibd
0
# dynamic: delete from: grep -c repairman ibdata1
0
drop table t1;
#
# Test delete+rollback+delete
#
create table t1 (
delete from delete_0;
create table delete_rollback_delete_0 (
a int auto_increment primary key,
b varchar(256),
c text) engine = innodb row_format=dynamic;
# Populate table with rows
begin;
delete from t1;
delete from delete_rollback_delete_0;
rollback;
delete from t1;
# restart mysqld so that all pages are flushed
# read all rows from table
select * from t1;
# dynamic: delete rollback: grep -c bicycle t1.ibd
0
# dynamic: delete rollback: grep -c bicycle ibdata1
0
# dynamic: delete rollback: grep -c repairman t1.ibd
0
# dynamic: delete rollback: grep -c repairman ibdata1
0
drop table t1;
#
# Test insert+rollback
#
create table t1 (
delete from delete_rollback_delete_0;
create table insert_rollback_0 (
a int auto_increment primary key,
b varchar(256),
c text) engine = innodb row_format=dynamic;
# Populate table with rows
begin;
rollback;
# restart mysqld so that all pages are flushed
# read all rows from table
select * from t1;
# dynamic: insert rollback: grep -c bicycle t1.ibd
0
# dynamic: insert rollback: grep -c bicycle ibdata1
0
# dynamic: insert rollback: grep -c repairman t1.ibd
0
# dynamic: insert rollback: grep -c repairman ibdata1
0
drop table t1;
SET GLOBAL innodb_fast_shutdown=0;
# delete_3.ibd
# delete_rollback_delete_3.ibd
# insert_rollback_3.ibd
# delete_2.ibd
# delete_rollback_delete_2.ibd
# insert_rollback_2.ibd
# delete_1.ibd
# delete_rollback_delete_1.ibd
# insert_rollback_1.ibd
# delete_0.ibd
# delete_rollback_delete_0.ibd
# insert_rollback_0.ibd
check table delete_3, delete_rollback_delete_3, insert_rollback_3;
Table Op Msg_type Msg_text
test.delete_3 check status OK
test.delete_rollback_delete_3 check status OK
test.insert_rollback_3 check status OK
drop table delete_3, delete_rollback_delete_3, insert_rollback_3;
check table delete_2, delete_rollback_delete_2, insert_rollback_2;
Table Op Msg_type Msg_text
test.delete_2 check status OK
test.delete_rollback_delete_2 check status OK
test.insert_rollback_2 check status OK
drop table delete_2, delete_rollback_delete_2, insert_rollback_2;
check table delete_1, delete_rollback_delete_1, insert_rollback_1;
Table Op Msg_type Msg_text
test.delete_1 check status OK
test.delete_rollback_delete_1 check status OK
test.insert_rollback_1 check status OK
drop table delete_1, delete_rollback_delete_1, insert_rollback_1;
check table delete_0, delete_rollback_delete_0, insert_rollback_0;
Table Op Msg_type Msg_text
test.delete_0 check status OK
test.delete_rollback_delete_0 check status OK
test.insert_rollback_0 check status OK
drop table delete_0, delete_rollback_delete_0, insert_rollback_0;
show variables like 'innodb_%scrub_data%';
Variable_name Value
innodb_background_scrub_data_check_interval 3600

View File

@@ -11,66 +11,146 @@ innodb_background_scrub_data_uncompressed ON
innodb_immediate_scrub_data_uncompressed OFF
# make sure spaces are checked quickly
SET GLOBAL innodb_background_scrub_data_check_interval=1;
create table snapshot_status engine = myisam
select * from information_schema.global_status
where variable_name like 'innodb_scrub%';
truncate table snapshot_status;
insert into snapshot_status
select * from information_schema.global_status
where variable_name like 'innodb_scrub%';
#
# Test delete of records
#
create table t1 (
create table delete_3 (
a int auto_increment primary key,
b varchar(256),
c text, index(b)) engine = innodb row_format=dynamic;
c text,
index(b)) engine = innodb row_format=compressed;
# Populate table with rows
delete from t1;
#
# Test delete+rollback+delete
#
create table t2 (
delete from delete_3;
create table delete_rollback_delete_3 (
a int auto_increment primary key,
b varchar(256),
c text, index(b)) engine = innodb row_format=dynamic;
c text,
index(b)) engine = innodb row_format=compressed;
# Populate table with rows
begin;
delete from t2;
delete from delete_rollback_delete_3;
rollback;
delete from t2;
#
# Test insert+rollback
#
create table t3 (
delete from delete_rollback_delete_3;
create table insert_rollback_3 (
a int auto_increment primary key,
b varchar(256),
c text, index(b)) engine = innodb row_format=dynamic;
c text,
index(b)) engine = innodb row_format=compressed;
# Populate table with rows
begin;
rollback;
create table delete_2 (
a int auto_increment primary key,
b varchar(256),
c text,
index(b)) engine = innodb row_format=compact;
# Populate table with rows
delete from delete_2;
create table delete_rollback_delete_2 (
a int auto_increment primary key,
b varchar(256),
c text,
index(b)) engine = innodb row_format=compact;
# Populate table with rows
begin;
delete from delete_rollback_delete_2;
rollback;
delete from delete_rollback_delete_2;
create table insert_rollback_2 (
a int auto_increment primary key,
b varchar(256),
c text,
index(b)) engine = innodb row_format=compact;
# Populate table with rows
begin;
rollback;
create table delete_1 (
a int auto_increment primary key,
b varchar(256),
c text,
index(b)) engine = innodb row_format=redundant;
# Populate table with rows
delete from delete_1;
create table delete_rollback_delete_1 (
a int auto_increment primary key,
b varchar(256),
c text,
index(b)) engine = innodb row_format=redundant;
# Populate table with rows
begin;
delete from delete_rollback_delete_1;
rollback;
delete from delete_rollback_delete_1;
create table insert_rollback_1 (
a int auto_increment primary key,
b varchar(256),
c text,
index(b)) engine = innodb row_format=redundant;
# Populate table with rows
begin;
rollback;
create table delete_0 (
a int auto_increment primary key,
b varchar(256),
c text,
index(b)) engine = innodb row_format=dynamic;
# Populate table with rows
delete from delete_0;
create table delete_rollback_delete_0 (
a int auto_increment primary key,
b varchar(256),
c text,
index(b)) engine = innodb row_format=dynamic;
# Populate table with rows
begin;
delete from delete_rollback_delete_0;
rollback;
delete from delete_rollback_delete_0;
create table insert_rollback_0 (
a int auto_increment primary key,
b varchar(256),
c text,
index(b)) engine = innodb row_format=dynamic;
# Populate table with rows
begin;
rollback;
# start scrubbing threads
SET GLOBAL innodb_encryption_threads=5;
# Wait max 10 min for scrubbing
# Success!
# stop scrubbing threads
SET GLOBAL innodb_encryption_threads=0;
# restart mysqld so that all pages are flushed
# read all rows from table
select * from t1;
# dynamic: delete: grep -c bicycle t1.ibd
0
# dynamic: delete: grep -c repairman t1.ibd
0
# dynamic: delete rollback: grep -c bicycle t2.ibd
0
# dynamic: delete rollback: grep -c repairman t2.ibd
0
# dynamic: insert rollback: grep -c bicycle t3.ibd
0
# dynamic: insert rollback: grep -c repairman t3.ibd
0
drop table t1, t2, t3;
SET GLOBAL innodb_fast_shutdown=0;
# delete_3.ibd
# delete_rollback_delete_3.ibd
# insert_rollback_3.ibd
# delete_2.ibd
# delete_rollback_delete_2.ibd
# insert_rollback_2.ibd
# delete_1.ibd
# delete_rollback_delete_1.ibd
# insert_rollback_1.ibd
# delete_0.ibd
# delete_rollback_delete_0.ibd
# insert_rollback_0.ibd
check table delete_3, delete_rollback_delete_3, insert_rollback_3;
Table Op Msg_type Msg_text
test.delete_3 check status OK
test.delete_rollback_delete_3 check status OK
test.insert_rollback_3 check status OK
drop table delete_3, delete_rollback_delete_3, insert_rollback_3;
check table delete_2, delete_rollback_delete_2, insert_rollback_2;
Table Op Msg_type Msg_text
test.delete_2 check status OK
test.delete_rollback_delete_2 check status OK
test.insert_rollback_2 check status OK
drop table delete_2, delete_rollback_delete_2, insert_rollback_2;
check table delete_1, delete_rollback_delete_1, insert_rollback_1;
Table Op Msg_type Msg_text
test.delete_1 check status OK
test.delete_rollback_delete_1 check status OK
test.insert_rollback_1 check status OK
drop table delete_1, delete_rollback_delete_1, insert_rollback_1;
check table delete_0, delete_rollback_delete_0, insert_rollback_0;
Table Op Msg_type Msg_text
test.delete_0 check status OK
test.delete_rollback_delete_0 check status OK
test.insert_rollback_0 check status OK
drop table delete_0, delete_rollback_delete_0, insert_rollback_0;
show variables like 'innodb_%scrub_data%';
Variable_name Value
innodb_background_scrub_data_check_interval 3600
@@ -78,4 +158,3 @@ innodb_background_scrub_data_compressed ON
innodb_background_scrub_data_interval 604800
innodb_background_scrub_data_uncompressed ON
innodb_immediate_scrub_data_uncompressed OFF
drop table snapshot_status;

View File

@@ -1,71 +0,0 @@
# make sure spaces are checked quickly
SET GLOBAL innodb_background_scrub_data_check_interval=1;
#
# Test delete of records
#
create table t1 (
a int auto_increment primary key,
b varchar(256),
c text) engine = innodb row_format=compressed;
# Populate table with rows
delete from t1;
#
# Test delete+rollback+delete
#
create table t2 (
a int auto_increment primary key,
b varchar(256),
c text) engine = innodb row_format=compressed;
# Populate table with rows
begin;
delete from t2;
rollback;
delete from t2;
#
# Test insert+rollback
#
create table t3 (
a int auto_increment primary key,
b varchar(256),
c text) engine = innodb row_format=compressed;
# Populate table with rows
begin;
rollback;
# start scrubbing threads
SET GLOBAL innodb_encryption_threads=5;
# Wait max 10 min for scrubbing of this table
# Success!
# stop scrubbing threads
SET GLOBAL innodb_encryption_threads=0;
# Now there should be background scrubs
# restart mysqld so that all pages are flushed (encryption off)
# so that grep will find stuff
# read all rows from table
select * from t1;
select * from t2;
select * from t3;
# grep -c bicycle t1.ibd
0
# grep -c bicycle ibdata1
0
# grep -c repairman t1.ibd
0
# grep -c repairman ibdata1
0
# grep -c boondoggle t2.ibd
0
# grep -c boondoggle ibdata1
0
# grep -c waste t2.ibd
0
# grep -c waste ibdata1
0
# grep -c keso t3.ibd
0
# grep -c keso ibdata1
0
# grep -c kent t3.ibd
0
# grep -c kent ibdata1
0
drop table t1, t2, t3;

View File

@@ -1,147 +1,138 @@
-- source include/have_innodb.inc
-- source include/not_embedded.inc
-- source include/have_example_key_management_plugin.inc
-- source include/not_windows.inc
let $MYSQLD_DATADIR=`select @@datadir`;
let ib1_IBD = $MYSQLD_DATADIR/ibdata1;
let t1_IBD = $MYSQLD_DATADIR/test/t1.ibd;
let INNODB_PAGE_SIZE= `select @@innodb_page_size`;
create table snapshot_status engine = myisam
select * from information_schema.global_status
where variable_name like 'innodb_scrub%';
where variable_name like 'innodb_scrub_background%';
let $rowcount=500;
let $formatno = 3;
let $maxformatno= 4;
let $formatno= $maxformatno;
--echo # MDEV-8139 Fix scrubbing tests
--echo # FIXME: Add index(b) to each table; ensure that undo logs are scrubbed.
let $tableformat= (
a int auto_increment primary key,
b varchar(256),
c text) engine = innodb row_format;
while ($formatno)
{
dec $formatno;
let $format = `select case $formatno
when 1 then 'dynamic'
when 2 then 'redundant'
when 3 then 'compact'
when 0 then 'dynamic'
when 1 then 'redundant'
when 2 then 'compact'
when 3 then 'compressed'
end`;
let $t= delete_$formatno;
eval create table $t $tableformat=$format;
let $numinserts = $rowcount;
--disable_query_log
begin;
while ($numinserts)
{
dec $numinserts;
eval insert into $t(b,c) values ('repairman', repeat('unicycle', 1000));
}
commit;
--enable_query_log
eval delete from $t;
let $t= delete_rollback_delete_$formatno;
eval create table $t $tableformat=$format;
let $numinserts = $rowcount;
--disable_query_log
begin;
while ($numinserts)
{
dec $numinserts;
eval insert into $t(b,c) values ('breakhuman', repeat('bicycle', 1000));
}
commit;
--enable_query_log
begin;
eval delete from $t;
rollback;
eval delete from $t;
let $t= insert_rollback_$formatno;
eval create table $t $tableformat=$format;
let $numinserts = $rowcount;
begin;
--disable_query_log
while ($numinserts)
{
dec $numinserts;
eval insert into $t(b,c) values ('wonderwoman', repeat('tricycle', 1000));
}
--enable_query_log
rollback;
}
SET GLOBAL innodb_fast_shutdown=0;
-- source include/shutdown_mysqld.inc
let SEARCH_ABORT= FOUND;
let SEARCH_PATTERN= (un|b|tr)icycle|(repair|breakhu|wonderwo)man;
let SEARCH_RANGE= 12582912;
let SEARCH_FILE= $MYSQLD_DATADIR/ibdata1;
# We may randomly find copies of unscrubbed pages in the doublewrite buffer.
# Let us scrub the doublewrite buffer ourselves.
perl;
use Fcntl 'SEEK_SET';
my $page_size = $ENV{INNODB_PAGE_SIZE};
open(FILE, "+<", "$ENV{SEARCH_FILE}") or die "cannot open: $!\n";
seek(FILE, $page_size * 64, SEEK_SET) or die "cannot seek: $!\n";
print(FILE chr(0) x ($page_size * 128)) or die "cannot write: $!\n";
close FILE or die "cannot close: $!\n";;
EOF
-- source include/search_pattern_in_file.inc
let $formatno= $maxformatno;
while ($formatno)
{
dec $formatno;
-- echo #
-- echo # Test delete of records
-- echo #
eval create table t1 (
a int auto_increment primary key,
b varchar(256),
c text) engine = innodb row_format=$format;
let $numinserts = $rowcount;
-- echo # Populate table with rows
--disable_query_log
while ($numinserts)
{
dec $numinserts;
insert into t1(b,c) values ('bicycle', repeat('repairman', 1000));
let $t= delete_$formatno.ibd;
let SEARCH_FILE= $MYSQLD_DATADIR/test/$t;
-- echo # $t
-- source include/search_pattern_in_file.inc
let $t= delete_rollback_delete_$formatno.ibd;
let SEARCH_FILE= $MYSQLD_DATADIR/test/$t;
-- echo # $t
-- source include/search_pattern_in_file.inc
let $t= insert_rollback_$formatno.ibd;
let SEARCH_FILE= $MYSQLD_DATADIR/test/$t;
-- echo # $t
-- source include/search_pattern_in_file.inc
}
--enable_query_log
delete from t1;
-- source include/start_mysqld.inc
-- echo # restart mysqld so that all pages are flushed
-- source include/restart_mysqld.inc
-- echo # read all rows from table
-- disable_result_log
select * from t1;
-- enable_result_log
-- echo # $format: delete from: grep -c bicycle t1.ibd
-- exec grep -c bicycle $t1_IBD || true
-- echo # $format: delete from: grep -c bicycle ibdata1
-- exec grep -c bicycle $ib1_IBD || true
-- echo # $format: delete from: grep -c repairman t1.ibd
-- exec grep -c repairman $t1_IBD || true
-- echo # $format: delete from: grep -c repairman ibdata1
-- exec grep -c repairman $ib1_IBD || true
drop table t1;
-- echo #
-- echo # Test delete+rollback+delete
-- echo #
eval create table t1 (
a int auto_increment primary key,
b varchar(256),
c text) engine = innodb row_format=$format;
let $numinserts = $rowcount;
-- echo # Populate table with rows
--disable_query_log
while ($numinserts)
let $formatno= $maxformatno;
while ($formatno)
{
dec $numinserts;
insert into t1(b,c) values ('bicycle', repeat('repairman', 1000));
}
--enable_query_log
dec $formatno;
begin;
delete from t1;
rollback;
delete from t1;
let $t= delete_$formatno, delete_rollback_delete_$formatno, insert_rollback_$formatno;
-- echo # restart mysqld so that all pages are flushed
-- source include/restart_mysqld.inc
-- echo # read all rows from table
-- disable_result_log
select * from t1;
-- enable_result_log
-- echo # $format: delete rollback: grep -c bicycle t1.ibd
-- exec grep -c bicycle $t1_IBD || true
-- echo # $format: delete rollback: grep -c bicycle ibdata1
-- exec grep -c bicycle $ib1_IBD || true
-- echo # $format: delete rollback: grep -c repairman t1.ibd
-- exec grep -c repairman $t1_IBD || true
-- echo # $format: delete rollback: grep -c repairman ibdata1
-- exec grep -c repairman $ib1_IBD || true
drop table t1;
-- echo #
-- echo # Test insert+rollback
-- echo #
eval create table t1 (
a int auto_increment primary key,
b varchar(256),
c text) engine = innodb row_format=$format;
let $numinserts = $rowcount;
-- echo # Populate table with rows
begin;
--disable_query_log
while ($numinserts)
{
dec $numinserts;
insert into t1(b,c) values ('bicycle', repeat('repairman', 1000));
}
--enable_query_log
rollback;
-- echo # restart mysqld so that all pages are flushed
-- source include/restart_mysqld.inc
-- echo # read all rows from table
-- disable_result_log
select * from t1;
-- enable_result_log
-- echo # $format: insert rollback: grep -c bicycle t1.ibd
-- exec grep -c bicycle $t1_IBD || true
-- echo # $format: insert rollback: grep -c bicycle ibdata1
-- exec grep -c bicycle $ib1_IBD || true
-- echo # $format: insert rollback: grep -c repairman t1.ibd
-- exec grep -c repairman $t1_IBD || true
-- echo # $format: insert rollback: grep -c repairman ibdata1
-- exec grep -c repairman $ib1_IBD || true
drop table t1;
eval check table $t;
eval drop table $t;
}
show variables like 'innodb_%scrub_data%';

View File

@@ -1,13 +1,9 @@
-- source include/have_innodb.inc
-- source include/not_embedded.inc
-- source include/have_example_key_management_plugin.inc
-- source include/not_windows.inc
let $MYSQLD_DATADIR=`select @@datadir`;
let ib1_IBD = $MYSQLD_DATADIR/ibdata1;
let t1_IBD = $MYSQLD_DATADIR/test/t1.ibd;
let t2_IBD = $MYSQLD_DATADIR/test/t2.ibd;
let t3_IBD = $MYSQLD_DATADIR/test/t3.ibd;
let INNODB_PAGE_SIZE= `select @@innodb_page_size`;
--echo #
--echo # immediate scrubbing is off
@@ -18,80 +14,67 @@ show variables like 'innodb_%scrub_data%';
-- echo # make sure spaces are checked quickly
SET GLOBAL innodb_background_scrub_data_check_interval=1;
create table snapshot_status engine = myisam
select * from information_schema.global_status
where variable_name like 'innodb_scrub%';
let $rowcount=500;
let $formatno = 1;
let $maxformatno= 4;
let $formatno= $maxformatno;
let $tableformat= (
a int auto_increment primary key,
b varchar(256),
c text,
index(b)) engine = innodb row_format;
while ($formatno)
{
let $format = `select case $formatno
when 1 then 'dynamic'
when 2 then 'redundant'
when 3 then 'compact'
when 4 then 'compressed'
end`;
dec $formatno;
let $format = `select case $formatno
when 0 then 'dynamic'
when 1 then 'redundant'
when 2 then 'compact'
when 3 then 'compressed'
end`;
truncate table snapshot_status;
insert into snapshot_status
select * from information_schema.global_status
where variable_name like 'innodb_scrub%';
-- echo #
-- echo # Test delete of records
-- echo #
eval create table t1 (
a int auto_increment primary key,
b varchar(256),
c text, index(b)) engine = innodb row_format=$format;
let $t= delete_$formatno;
eval create table $t $tableformat=$format;
let $numinserts = $rowcount;
-- echo # Populate table with rows
--disable_query_log
begin;
while ($numinserts)
{
dec $numinserts;
insert into t1(b,c) values ('bicycle', repeat('repairman', 1000));
eval insert into $t(b,c) values ('unicycle', repeat('wonderwoman', 1000));
}
commit;
--enable_query_log
delete from t1;
eval delete from $t;
-- echo #
-- echo # Test delete+rollback+delete
-- echo #
let $t= delete_rollback_delete_$formatno;
eval create table t2 (
a int auto_increment primary key,
b varchar(256),
c text, index(b)) engine = innodb row_format=$format;
eval create table $t $tableformat=$format;
let $numinserts = $rowcount;
-- echo # Populate table with rows
--disable_query_log
begin;
while ($numinserts)
{
dec $numinserts;
insert into t2(b,c) values ('bicycle', repeat('repairman', 1000));
eval insert into $t(b,c) values ('bicycle', repeat('repairman', 1000));
}
commit;
--enable_query_log
begin;
delete from t2;
eval delete from $t;
rollback;
delete from t2;
eval delete from $t;
-- echo #
-- echo # Test insert+rollback
-- echo #
let $t= insert_rollback_$formatno;
eval create table t3 (
a int auto_increment primary key,
b varchar(256),
c text, index(b)) engine = innodb row_format=$format;
eval create table $t $tableformat=$format;
let $numinserts = $rowcount;
-- echo # Populate table with rows
@@ -100,11 +83,12 @@ begin;
while ($numinserts)
{
dec $numinserts;
insert into t3(b,c) values ('bicycle', repeat('repairman', 1000));
eval insert into $t(b,c) values ('tricycle', repeat('superhuman', 1000));
}
--enable_query_log
rollback;
}
-- echo # start scrubbing threads
SET GLOBAL innodb_encryption_threads=5;
@@ -130,35 +114,57 @@ if (!$success)
-- die Timeout waiting for background threads
}
-- echo # Success!
-- echo # stop scrubbing threads
SET GLOBAL innodb_encryption_threads=0;
SET GLOBAL innodb_fast_shutdown=0;
-- source include/shutdown_mysqld.inc
-- echo # restart mysqld so that all pages are flushed
-- source include/restart_mysqld.inc
-- echo # read all rows from table
-- disable_result_log
select * from t1;
-- enable_result_log
let SEARCH_ABORT= FOUND;
let SEARCH_PATTERN= (un|b|tr)icycle|(repair|breakhu|wonderwo)man;
let SEARCH_RANGE= 12582912;
let SEARCH_FILE= $MYSQLD_DATADIR/ibdata1;
-- echo # $format: delete: grep -c bicycle t1.ibd
-- exec grep -c bicycle $t1_IBD || true
-- echo # $format: delete: grep -c repairman t1.ibd
-- exec grep -c repairman $t1_IBD || true
# We may randomly find copies of unscrubbed pages in the doublewrite buffer.
# Let us scrub the doublewrite buffer ourselves.
perl;
use Fcntl 'SEEK_SET';
my $page_size = $ENV{INNODB_PAGE_SIZE};
open(FILE, "+<", "$ENV{SEARCH_FILE}") or die "cannot open: $!\n";
seek(FILE, $page_size * 64, SEEK_SET) or die "cannot seek: $!\n";
print(FILE chr(0) x ($page_size * 128)) or die "cannot write: $!\n";
close FILE or die "cannot close: $!\n";;
EOF
-- echo # $format: delete rollback: grep -c bicycle t2.ibd
-- exec grep -c bicycle $t2_IBD || true
-- echo # $format: delete rollback: grep -c repairman t2.ibd
-- exec grep -c repairman $t2_IBD || true
-- source include/search_pattern_in_file.inc
-- echo # $format: insert rollback: grep -c bicycle t3.ibd
-- exec grep -c bicycle $t3_IBD || true
-- echo # $format: insert rollback: grep -c repairman t3.ibd
-- exec grep -c repairman $t3_IBD || true
let $formatno= $maxformatno;
while ($formatno)
{
dec $formatno;
drop table t1, t2, t3;
let $t= delete_$formatno.ibd;
let SEARCH_FILE= $MYSQLD_DATADIR/test/$t;
-- echo # $t
-- source include/search_pattern_in_file.inc
let $t= delete_rollback_delete_$formatno.ibd;
let SEARCH_FILE= $MYSQLD_DATADIR/test/$t;
-- echo # $t
-- source include/search_pattern_in_file.inc
let $t= insert_rollback_$formatno.ibd;
let SEARCH_FILE= $MYSQLD_DATADIR/test/$t;
-- echo # $t
-- source include/search_pattern_in_file.inc
}
-- source include/start_mysqld.inc
let $formatno= $maxformatno;
while ($formatno)
{
dec $formatno;
let $t= delete_$formatno, delete_rollback_delete_$formatno, insert_rollback_$formatno;
eval check table $t;
eval drop table $t;
}
show variables like 'innodb_%scrub_data%';
drop table snapshot_status;

View File

@@ -1,9 +0,0 @@
--innodb-file-per-table=1
--innodb-file-format=Barracuda
--innodb-immediate-scrub-data-uncompressed=ON
--innodb-background-scrub-data-uncompressed=ON
--innodb-background-scrub-data-compressed=ON
--loose-innodb-debug-force-scrubbing=ON
--innodb-encrypt-tables=OFF
--innodb-encrypt-log=OFF
--innodb-tablespaces-scrubbing

View File

@@ -1,161 +0,0 @@
-- source include/have_innodb.inc
-- source include/not_embedded.inc
-- source include/have_example_key_management_plugin.inc
-- source include/not_windows.inc
let $MYSQLD_DATADIR=`select @@datadir`;
let ib1_IBD = $MYSQLD_DATADIR/ibdata1;
let t1_IBD = $MYSQLD_DATADIR/test/t1.ibd;
let t2_IBD = $MYSQLD_DATADIR/test/t2.ibd;
let t3_IBD = $MYSQLD_DATADIR/test/t3.ibd;
let $rowcount=500;
-- echo # make sure spaces are checked quickly
SET GLOBAL innodb_background_scrub_data_check_interval=1;
-- echo #
-- echo # Test delete of records
-- echo #
eval create table t1 (
a int auto_increment primary key,
b varchar(256),
c text) engine = innodb row_format=compressed;
let $numinserts = $rowcount;
-- echo # Populate table with rows
--disable_query_log
while ($numinserts)
{
dec $numinserts;
insert into t1(b,c) values ('bicycle', repeat('repairman', 1000));
}
--enable_query_log
delete from t1;
-- echo #
-- echo # Test delete+rollback+delete
-- echo #
eval create table t2 (
a int auto_increment primary key,
b varchar(256),
c text) engine = innodb row_format=compressed;
let $numinserts = $rowcount;
-- echo # Populate table with rows
--disable_query_log
while ($numinserts)
{
dec $numinserts;
insert into t2(b,c) values ('boondoggle', repeat('waste of time', 1000));
}
--enable_query_log
begin;
delete from t2;
rollback;
delete from t2;
-- echo #
-- echo # Test insert+rollback
-- echo #
eval create table t3 (
a int auto_increment primary key,
b varchar(256),
c text) engine = innodb row_format=compressed;
let $numinserts = $rowcount;
-- echo # Populate table with rows
begin;
--disable_query_log
while ($numinserts)
{
dec $numinserts;
insert into t3(b,c) values ('keso', repeat('kent', 1000));
}
--enable_query_log
rollback;
-- echo # start scrubbing threads
SET GLOBAL innodb_encryption_threads=5;
-- echo # Wait max 10 min for scrubbing of this table
let $cnt=600;
while ($cnt)
{
let $success=`SELECT COUNT(*) = 0
FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_SCRUBBING
WHERE LAST_SCRUB_COMPLETED IS NULL AND ( NAME like 'test/%' OR SPACE = 0 )`;
if ($success)
{
let $cnt=0;
}
if (!$success)
{
real_sleep 1;
dec $cnt;
}
}
if (!$success)
{
SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_SCRUBBING;
SHOW STATUS LIKE 'innodb_%scrub%';
-- die Timeout waiting for background threads
}
-- echo # Success!
-- echo # stop scrubbing threads
SET GLOBAL innodb_encryption_threads=0;
--echo # Now there should be background scrubs
let $success=`select sum(variable_value) > 0
from information_schema.global_status
where variable_name in ('innodb_scrub_background_page_reorganizations',
'innodb_scrub_background_page_splits')`;
if (!$success) {
show status like 'innodb_scrub%';
}
-- echo # restart mysqld so that all pages are flushed (encryption off)
-- echo # so that grep will find stuff
-- source include/restart_mysqld.inc
-- echo # read all rows from table
-- disable_result_log
select * from t1;
select * from t2;
select * from t3;
-- enable_result_log
-- echo # grep -c bicycle t1.ibd
-- exec grep -c bicycle $t1_IBD || true
-- echo # grep -c bicycle ibdata1
-- exec grep -c bicycle $ib1_IBD || true
-- echo # grep -c repairman t1.ibd
-- exec grep -c repairman $t1_IBD || true
-- echo # grep -c repairman ibdata1
-- exec grep -c repairman $ib1_IBD || true
-- echo # grep -c boondoggle t2.ibd
-- exec grep -c boondoggle $t2_IBD || true
-- echo # grep -c boondoggle ibdata1
-- exec grep -c boondoggle $ib1_IBD || true
-- echo # grep -c waste t2.ibd
-- exec grep -c waste $t2_IBD || true
-- echo # grep -c waste ibdata1
-- exec grep -c waste $ib1_IBD || true
-- echo # grep -c keso t3.ibd
-- exec grep -c keso $t3_IBD || true
-- echo # grep -c keso ibdata1
-- exec grep -c keso $ib1_IBD || true
-- echo # grep -c kent t3.ibd
-- exec grep -c kent $t3_IBD || true
-- echo # grep -c kent ibdata1
-- exec grep -c kent $ib1_IBD || true
drop table t1, t2, t3;

View File

@@ -4,6 +4,7 @@ CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
SET SESSION wsrep_on = OFF;
SET SESSION wsrep_on = ON;
SET global wsrep_sync_wait=0;
connection node_3;
START SLAVE;
include/wait_for_slave_param.inc [Slave_IO_Running]
@@ -16,6 +17,7 @@ INSERT INTO t1 VALUES (1);
connection node_3;
connection node_1;
DROP TABLE t1;
SET global wsrep_sync_wait=7;
connection node_3;
STOP SLAVE;
RESET SLAVE ALL;

View File

@@ -21,6 +21,15 @@ Variable_name Value
wsrep_cluster_status non-Primary
SELECT * FROM t1;
ERROR 08S01: WSREP has not yet prepared node for application use
SELECT @@wsrep_dirty_reads;
@@wsrep_dirty_reads
0
SELECT 2;
2
2
SELECT 2+2 FROM DUAL;
2+2
4
SET @@session.wsrep_dirty_reads=ON;
SELECT * FROM t1;
i

View File

@@ -11,12 +11,16 @@
--enable_query_log
--connection node_1
--let $wsrep_sync_wait_state= `SELECT @@global.wsrep_sync_wait;`
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
SET SESSION wsrep_on = OFF;
--let $wait_condition = SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'
--source include/wait_condition.inc
SET SESSION wsrep_on = ON;
#wsrep_sync_wait is set to zero because when slave tries to connect it it ask for queries like SELECT UNIX_TIMESTAMP() on node 1 which will fail, causing
#a warning in slave error log.
SET global wsrep_sync_wait=0;
--connection node_3
START SLAVE;
@@ -47,6 +51,7 @@ INSERT INTO t1 VALUES (1);
--connection node_1
DROP TABLE t1;
--eval SET global wsrep_sync_wait=$wsrep_sync_wait_state
--connection node_3
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'
--source include/wait_condition.inc

View File

@@ -37,6 +37,11 @@ SHOW STATUS LIKE 'wsrep_cluster_status';
--error ER_UNKNOWN_COM_ERROR
SELECT * FROM t1;
#Select query which does not access table should be allowed MDEV-11016
SELECT @@wsrep_dirty_reads;
SELECT 2;
SELECT 2+2 FROM DUAL;
SET @@session.wsrep_dirty_reads=ON;
SELECT * FROM t1;

View File

@@ -1,3 +1,4 @@
--source include/not_valgrind.inc
--disable_ps_protocol
SET GLOBAL net_write_timeout = 900;

View File

@@ -7,8 +7,5 @@ loose-thread_pool_max_threads= 2
extra-port= @ENV.MASTER_EXTRA_PORT
extra-max-connections=1
[client]
connect-timeout= 2
[ENV]
MASTER_EXTRA_PORT= @OPT.port

View File

@@ -15,23 +15,26 @@ SET optimizer_switch=@save_optimizer_switch;
# connections on the extra port.
# First set two connections running, and check that extra connection
# on normal port fails due to--thread-pool-max_threads=2
connection default;
# on normal port fails due to --thread-pool-max-threads=2.
# We can afford using a really long sleep, because we won't wait
# till it ends, we'll interrupt it as soon as we don't need it anymore
# Sleep for slightly longer than 5 sec to trigger MDEV-4566
# (abort in interruptible wait connection check)
send SELECT sleep(5.5);
connection default;
--let $con1_id= `SELECT CONNECTION_ID()`
send SELECT sleep(50);
--sleep 1
connect(con2,localhost,root,,);
connection con2;
send SELECT sleep(5);
--let $con2_id= `SELECT CONNECTION_ID()`
send SELECT sleep(50);
--sleep 0.5
--disable_abort_on_error
--disable_result_log
--disable_query_log
connect(con3,localhost,root,,);
connect(con3,localhost,root,,,,,connect_timeout=2);
--enable_query_log
--enable_result_log
--enable_abort_on_error
@@ -45,24 +48,15 @@ if ($error)
--echo # -- Success: more than --thread_pool_max_threads normal connections not possible
}
connection default;
--reap
connection con2;
--reap
# Now try again, but this time use the extra port to successfully connect.
connection default;
send SELECT sleep(5);
connection con2;
send SELECT sleep(5);
--sleep 1
connect(extracon,127.0.0.1,root,,test,$MASTER_EXTRA_PORT,);
connection extracon;
SELECT 'Connection on extra port ok';
# Here, sleep just for slightly longer than 5 sec to trigger MDEV-4566
# (abort in interruptible wait connection check).
send SELECT sleep(5.5);
connect(extracon2,127.0.0.1,root,,test,$MASTER_EXTRA_PORT,);
connection extracon2;
SELECT 'Connection on extra port 2 ok';
@@ -70,7 +64,7 @@ SELECT 'Connection on extra port 2 ok';
--disable_abort_on_error
--disable_result_log
--disable_query_log
connect(extracon3,127.0.0.1,root,,test,$MASTER_EXTRA_PORT,);
connect(extracon3,127.0.0.1,root,,test,$MASTER_EXTRA_PORT,,connect_timeout=2);
--enable_query_log
--enable_result_log
--enable_abort_on_error
@@ -84,7 +78,16 @@ if ($error)
--echo # -- Success: more than --extra-max-connections + 1 normal connections not possible
}
connection extracon2;
--replace_result $con1_id <default_connection_ID>
eval KILL QUERY $con1_id;
--replace_result $con2_id <con2_connection_ID>
eval KILL QUERY $con2_id;
connection default;
--reap
connection con2;
--reap
connection extracon;
--reap

View File

@@ -419,8 +419,7 @@ unpack_row(rpl_group_info *rgi,
/*
Add Extra slave persistent columns
*/
int error= 0;
if ((error= fill_extra_persistent_columns(table, cols->n_bits)))
if (int error= fill_extra_persistent_columns(table, cols->n_bits))
DBUG_RETURN(error);
/*

View File

@@ -523,6 +523,7 @@ void init_update_queries(void)
server_command_flags[COM_STMT_RESET]= CF_SKIP_QUESTIONS | CF_SKIP_WSREP_CHECK;
server_command_flags[COM_STMT_EXECUTE]= CF_SKIP_WSREP_CHECK;
server_command_flags[COM_STMT_SEND_LONG_DATA]= CF_SKIP_WSREP_CHECK;
server_command_flags[COM_REGISTER_SLAVE]= CF_SKIP_WSREP_CHECK;
server_command_flags[COM_MULTI]= CF_SKIP_WSREP_CHECK | CF_NO_COM_MULTI;
/* Initialize the sql command flags array. */
@@ -3080,7 +3081,7 @@ mysql_execute_command(THD *thd)
} /* endif unlikely slave */
#endif
#ifdef WITH_WSREP
if (WSREP(thd))
if (wsrep && WSREP(thd))
{
/*
change LOCK TABLE WRITE to transaction
@@ -3108,7 +3109,7 @@ mysql_execute_command(THD *thd)
/*
Bail out if DB snapshot has not been installed. SET and SHOW commands,
however, are always allowed.
Select query is also allowed if it does not access any table.
We additionally allow all other commands that do not change data in
case wsrep_dirty_reads is enabled.
*/
@@ -3116,6 +3117,8 @@ mysql_execute_command(THD *thd)
!wsrep_is_show_query(lex->sql_command) &&
!(thd->variables.wsrep_dirty_reads &&
!is_update_query(lex->sql_command)) &&
!(lex->sql_command == SQLCOM_SELECT &&
!all_tables) &&
!wsrep_node_is_ready(thd))
goto error;
}

View File

@@ -178,7 +178,7 @@ extern wsrep_seqno_t wsrep_locked_seqno;
strcmp(wsrep_provider, WSREP_NONE))
#define WSREP(thd) \
(WSREP_ON && wsrep && (thd && thd->variables.wsrep_on))
(WSREP_ON && thd->variables.wsrep_on)
#define WSREP_CLIENT(thd) \
(WSREP(thd) && thd->wsrep_client_thread)

View File

@@ -3150,18 +3150,14 @@ calc_buf_pool_size:
/** This is the thread for resizing buffer pool. It waits for an event and
when waked up either performs a resizing and sleeps again.
@param[in] arg a dummy parameter required by os_thread_create.
@return this function does not return, calls os_thread_exit()
*/
extern "C"
os_thread_ret_t
DECLARE_THREAD(buf_resize_thread)(
void* arg MY_ATTRIBUTE((unused)))
DECLARE_THREAD(buf_resize_thread)(void*)
{
my_thread_init();
srv_buf_resize_thread_active = true;
while (srv_shutdown_state == SRV_SHUTDOWN_NONE) {
os_event_wait(srv_buf_resize_event);
os_event_reset(srv_buf_resize_event);

View File

@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
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
@@ -778,10 +779,7 @@ again.
@return this function does not return, it calls os_thread_exit() */
extern "C"
os_thread_ret_t
DECLARE_THREAD(buf_dump_thread)(
/*============================*/
void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter
required by os_thread_create */
DECLARE_THREAD(buf_dump_thread)(void*)
{
ut_ad(!srv_read_only_mode);
/* JAN: TODO: MySQL 5.7 PSI
@@ -789,8 +787,6 @@ DECLARE_THREAD(buf_dump_thread)(
pfs_register_thread(buf_dump_thread_key);
#endif */ /* UNIV_PFS_THREAD */
srv_buf_dump_thread_active = TRUE;
buf_dump_status(STATUS_VERBOSE, "Dumping of buffer pool not started");
buf_load_status(STATUS_VERBOSE, "Loading of buffer pool not started");
@@ -820,7 +816,7 @@ DECLARE_THREAD(buf_dump_thread)(
keep going even if we are in a shutdown state */);
}
srv_buf_dump_thread_active = FALSE;
srv_buf_dump_thread_active = false;
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit and not use return() to exit. */

View File

@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
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
@@ -399,10 +400,7 @@ statistics.
@return this function does not return, it calls os_thread_exit() */
extern "C"
os_thread_ret_t
DECLARE_THREAD(dict_stats_thread)(
/*==============================*/
void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter
required by os_thread_create */
DECLARE_THREAD(dict_stats_thread)(void*)
{
ut_a(!srv_read_only_mode);
@@ -412,8 +410,6 @@ DECLARE_THREAD(dict_stats_thread)(
*/
#endif /* UNIV_PFS_THREAD */
srv_dict_stats_thread_active = TRUE;
while (!dict_stats_start_shutdown) {
/* Wake up periodically even if not signaled. This is
@@ -445,7 +441,7 @@ DECLARE_THREAD(dict_stats_thread)(
os_event_reset(dict_stats_event);
}
srv_dict_stats_thread_active = FALSE;
srv_dict_stats_thread_active = false;
os_event_set(dict_stats_shutdown_event);
my_thread_end();

View File

@@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (C) 2013, 2015, Google Inc. All Rights Reserved.
Copyright (C) 2014, 2017, MariaDB Corporation. All Rights Reserved.
Copyright (c) 2014, 2017, MariaDB Corporation. All Rights Reserved.
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
@@ -54,7 +54,7 @@ UNIV_INTERN ulong srv_encrypt_tables = 0;
UNIV_INTERN uint srv_n_fil_crypt_threads = 0;
/** No of key rotation threads started */
static uint srv_n_fil_crypt_threads_started = 0;
UNIV_INTERN uint srv_n_fil_crypt_threads_started = 0;
/** At this age or older a space/page will be rotated */
UNIV_INTERN uint srv_fil_crypt_rotate_key_age = 1;
@@ -63,7 +63,7 @@ UNIV_INTERN uint srv_fil_crypt_rotate_key_age = 1;
static os_event_t fil_crypt_event;
/** Event to signal TO the key rotation threads. */
static os_event_t fil_crypt_threads_event;
UNIV_INTERN os_event_t fil_crypt_threads_event;
/** Event for waking up threads throttle */
static os_event_t fil_crypt_throttle_sleep_event;
@@ -1207,10 +1207,21 @@ struct rotate_thread_t {
btr_scrub_t scrub_data; /* thread local data used by btr_scrub-functions
* when iterating pages of tablespace */
/* check if this thread should shutdown */
/** @return whether this thread should terminate */
bool should_shutdown() const {
return ! (srv_shutdown_state == SRV_SHUTDOWN_NONE &&
thread_no < srv_n_fil_crypt_threads);
switch (srv_shutdown_state) {
case SRV_SHUTDOWN_NONE:
case SRV_SHUTDOWN_CLEANUP:
return thread_no >= srv_n_fil_crypt_threads;
case SRV_SHUTDOWN_EXIT_THREADS:
/* srv_init_abort() must have been invoked */
case SRV_SHUTDOWN_FLUSH_PHASE:
return true;
case SRV_SHUTDOWN_LAST_PHASE:
break;
}
ut_ad(0);
return true;
}
};
@@ -2378,18 +2389,6 @@ fil_crypt_threads_init()
}
}
/*********************************************************************
End threads for key rotation */
UNIV_INTERN
void
fil_crypt_threads_end()
/*===================*/
{
if (fil_crypt_threads_inited) {
fil_crypt_set_thread_cnt(0);
}
}
/*********************************************************************
Clean up key rotation threads resources */
UNIV_INTERN
@@ -2400,6 +2399,7 @@ fil_crypt_threads_cleanup()
if (!fil_crypt_threads_inited) {
return;
}
ut_a(!srv_n_fil_crypt_threads_started);
os_event_destroy(fil_crypt_event);
os_event_destroy(fil_crypt_threads_event);
mutex_free(&fil_crypt_threads_mutex);

View File

@@ -384,115 +384,6 @@ flst_remove(
mlog_write_ulint(base + FLST_LEN, len - 1, MLOG_4BYTES, mtr);
}
/********************************************************************//**
Cuts off the tail of the list, including the node given. The number of
nodes which will be removed must be provided by the caller, as this function
does not measure the length of the tail. */
void
flst_cut_end(
/*=========*/
flst_base_node_t* base, /*!< in: pointer to base node of list */
flst_node_t* node2, /*!< in: first node to remove */
ulint n_nodes,/*!< in: number of nodes to remove,
must be >= 1 */
mtr_t* mtr) /*!< in: mini-transaction handle */
{
ulint space;
flst_node_t* node1;
fil_addr_t node1_addr;
fil_addr_t node2_addr;
ulint len;
ut_ad(mtr && node2 && base);
ut_ad(mtr_memo_contains_page_flagged(mtr, base,
MTR_MEMO_PAGE_X_FIX
| MTR_MEMO_PAGE_SX_FIX));
ut_ad(mtr_memo_contains_page_flagged(mtr, node2,
MTR_MEMO_PAGE_X_FIX
| MTR_MEMO_PAGE_SX_FIX));
ut_ad(n_nodes > 0);
buf_ptr_get_fsp_addr(node2, &space, &node2_addr);
node1_addr = flst_get_prev_addr(node2, mtr);
if (!fil_addr_is_null(node1_addr)) {
/* Update next field of node1 */
if (node1_addr.page == node2_addr.page) {
node1 = page_align(node2) + node1_addr.boffset;
} else {
bool found;
const page_size_t& page_size
= fil_space_get_page_size(space, &found);
ut_ad(found);
node1 = fut_get_ptr(space, page_size,
node1_addr, RW_SX_LATCH, mtr);
}
flst_write_addr(node1 + FLST_NEXT, fil_addr_null, mtr);
} else {
/* node2 was first in list: update the field in base */
flst_write_addr(base + FLST_FIRST, fil_addr_null, mtr);
}
flst_write_addr(base + FLST_LAST, node1_addr, mtr);
/* Update len of base node */
len = flst_get_len(base);
ut_ad(len >= n_nodes);
mlog_write_ulint(base + FLST_LEN, len - n_nodes, MLOG_4BYTES, mtr);
}
/********************************************************************//**
Cuts off the tail of the list, not including the given node. The number of
nodes which will be removed must be provided by the caller, as this function
does not measure the length of the tail. */
void
flst_truncate_end(
/*==============*/
flst_base_node_t* base, /*!< in: pointer to base node of list */
flst_node_t* node2, /*!< in: first node not to remove */
ulint n_nodes,/*!< in: number of nodes to remove */
mtr_t* mtr) /*!< in: mini-transaction handle */
{
fil_addr_t node2_addr;
ulint len;
ulint space;
ut_ad(mtr && node2 && base);
ut_ad(mtr_memo_contains_page_flagged(mtr, base,
MTR_MEMO_PAGE_X_FIX
| MTR_MEMO_PAGE_SX_FIX));
ut_ad(mtr_memo_contains_page_flagged(mtr, node2,
MTR_MEMO_PAGE_X_FIX
| MTR_MEMO_PAGE_SX_FIX));
if (n_nodes == 0) {
ut_ad(fil_addr_is_null(flst_get_next_addr(node2, mtr)));
return;
}
buf_ptr_get_fsp_addr(node2, &space, &node2_addr);
/* Update next field of node2 */
flst_write_addr(node2 + FLST_NEXT, fil_addr_null, mtr);
flst_write_addr(base + FLST_LAST, node2_addr, mtr);
/* Update len of base node */
len = flst_get_len(base);
ut_ad(len >= n_nodes);
mlog_write_ulint(base + FLST_LEN, len - n_nodes, MLOG_4BYTES, mtr);
}
/********************************************************************//**
Validates a file-based list.
@return TRUE if ok */

View File

@@ -1,10 +1,10 @@
/*****************************************************************************
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2017, MariaDB Corporation.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2012, Facebook Inc.
Copyright (c) 2013, 2017, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -262,7 +262,6 @@ static my_bool innodb_optimize_fulltext_only = FALSE;
static char* innodb_version_str = (char*) INNODB_VERSION_STR;
extern uint srv_n_fil_crypt_threads;
extern uint srv_fil_crypt_rotate_key_age;
extern uint srv_n_fil_crypt_iops;
@@ -4885,7 +4884,7 @@ innobase_commit_low(
#ifdef WITH_WSREP
THD* thd = (THD*)trx->mysql_thd;
const char* tmp = 0;
if (wsrep_on(thd)) {
if (thd && wsrep_on(thd)) {
#ifdef WSREP_PROC_INFO
char info[64];
info[sizeof(info) - 1] = '\0';

View File

@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2016, MariaDB Corporation.
Copyright (c) 2013, 2017, 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
@@ -389,15 +389,11 @@ buf_pool_resize();
/** This is the thread for resizing buffer pool. It waits for an event and
when waked up either performs a resizing and sleeps again.
@param[in] arg a dummy parameter required by os_thread_create.
@return this function does not return, calls os_thread_exit()
*/
extern "C"
os_thread_ret_t
DECLARE_THREAD(buf_resize_thread)(
/*==============================*/
void* arg); /*!< in: a dummy parameter
required by os_thread_create */
DECLARE_THREAD(buf_resize_thread)(void*);
/********************************************************************//**
Clears the adaptive hash index on all pages in the buffer pool. */

View File

@@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (C) 2013, 2015, Google Inc. All Rights Reserved.
Copyright (c) 2015, 2016, MariaDB Corporation.
Copyright (c) 2015, 2017, 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
@@ -26,6 +26,8 @@ Created 04/01/2015 Jan Lindström
#ifndef fil0crypt_h
#define fil0crypt_h
#include "os0event.h"
/**
* Magic pattern in start of crypt data on page 0
*/
@@ -45,6 +47,8 @@ typedef enum {
FIL_SPACE_ENCRYPTION_OFF = 2 /* Tablespace is not encrypted */
} fil_encryption_t;
extern os_event_t fil_crypt_threads_event;
/**
* CRYPT_SCHEME_UNENCRYPTED
*
@@ -391,12 +395,6 @@ fil_crypt_set_thread_cnt(
/*=====================*/
uint new_cnt); /*!< in: requested #threads */
/*********************************************************************
End threads for key rotation */
UNIV_INTERN
void
fil_crypt_threads_end();
/*********************************************************************
Cleanup resources for threads for key rotation */
UNIV_INTERN

View File

@@ -99,29 +99,6 @@ flst_remove(
flst_base_node_t* base, /*!< in: pointer to base node of list */
flst_node_t* node2, /*!< in: node to remove */
mtr_t* mtr); /*!< in: mini-transaction handle */
/********************************************************************//**
Cuts off the tail of the list, including the node given. The number of
nodes which will be removed must be provided by the caller, as this function
does not measure the length of the tail. */
void
flst_cut_end(
/*=========*/
flst_base_node_t* base, /*!< in: pointer to base node of list */
flst_node_t* node2, /*!< in: first node to remove */
ulint n_nodes,/*!< in: number of nodes to remove,
must be >= 1 */
mtr_t* mtr); /*!< in: mini-transaction handle */
/********************************************************************//**
Cuts off the tail of the list, not including the given node. The number of
nodes which will be removed must be provided by the caller, as this function
does not measure the length of the tail. */
void
flst_truncate_end(
/*==============*/
flst_base_node_t* base, /*!< in: pointer to base node of list */
flst_node_t* node2, /*!< in: first node not to remove */
ulint n_nodes,/*!< in: number of nodes to remove */
mtr_t* mtr); /*!< in: mini-transaction handle */
/** Get the length of a list.
@param[in] base base node
@return length */

View File

@@ -2,6 +2,7 @@
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2009, Google Inc.
Copyright (c) 2017, MariaDB Corporation
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -38,6 +39,7 @@ Created 12/9/1995 Heikki Tuuri
#include "sync0rw.h"
#include "log0crypt.h"
#include "log0types.h"
#include "os0event.h"
/** Redo log buffer */
struct log_t;
@@ -804,21 +806,13 @@ log_group_calc_lsn_offset(
lsn_t lsn,
const log_group_t* group);
extern os_event_t log_scrub_event;
/* log scrubbing speed, in bytes/sec */
extern ulonglong innodb_scrub_log_speed;
/*****************************************************************//**
This is the main thread for log scrub. It waits for an event and
when waked up fills current log block with dummy records and
sleeps again.
@return this function does not return, it calls os_thread_exit() */
extern "C" UNIV_INTERN
os_thread_ret_t
DECLARE_THREAD(log_scrub_thread)(
/*===============================*/
void* arg); /*!< in: a dummy parameter
required by os_thread_create */
/** Event to wake up log_scrub_thread */
extern os_event_t log_scrub_event;
/** Whether log_scrub_thread is active */
extern bool log_scrub_thread_active;
#ifndef UNIV_NONINL
#include "log0log.ic"

View File

@@ -331,6 +331,9 @@ extern ulong srv_undo_logs;
/** Maximum size of undo tablespace. */
extern unsigned long long srv_max_undo_log_size;
extern uint srv_n_fil_crypt_threads;
extern uint srv_n_fil_crypt_threads_started;
/** Rate at which UNDO records should be purged. */
extern ulong srv_purge_rseg_truncate_frequency;
@@ -501,22 +504,20 @@ extern my_bool srv_print_innodb_monitor;
extern my_bool srv_print_innodb_lock_monitor;
extern ibool srv_print_verbose_log;
extern ibool srv_monitor_active;
extern ibool srv_error_monitor_active;
extern bool srv_monitor_active;
extern bool srv_error_monitor_active;
/* TRUE during the lifetime of the buffer pool dump/load thread */
extern ibool srv_buf_dump_thread_active;
extern bool srv_buf_dump_thread_active;
/* true during the lifetime of the buffer pool resize thread */
extern bool srv_buf_resize_thread_active;
/* TRUE during the lifetime of the stats thread */
extern ibool srv_dict_stats_thread_active;
extern bool srv_dict_stats_thread_active;
/* TRUE if enable log scrubbing */
extern my_bool srv_scrub_log;
/* TRUE during the lifetime of the log scrub thread */
extern ibool srv_log_scrub_thread_active;
extern ulong srv_n_spin_wait_rounds;
extern ulong srv_n_free_tickets_to_enter;
@@ -933,14 +934,6 @@ srv_release_threads(
enum srv_thread_type type, /*!< in: thread type */
ulint n); /*!< in: number of threads to release */
/**********************************************************************//**
Check whether any background thread are active. If so print which thread
is active. Send the threads wakeup signal.
@return name of thread that is active or NULL */
const char*
srv_any_background_threads_are_active(void);
/*=======================================*/
/**********************************************************************//**
Wakeup the purge threads. */
void

View File

@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 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
@@ -111,11 +112,6 @@ srv_path_copy(
const char* table_name) /*!< in: source table name */
MY_ATTRIBUTE((nonnull, warn_unused_result));
/**
Shutdown all background threads created by InnoDB. */
void
srv_shutdown_all_bg_threads();
/** Get the meta-data filename from the table name for a
single-table tablespace.
@param[in] table table object

View File

@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2014, 2016, MariaDB Corporation.
Copyright (c) 2014, 2017, MariaDB Corporation. All Rights Reserved.
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
@@ -509,11 +509,7 @@ A thread which wakes up threads whose lock wait may have lasted too long.
@return a dummy parameter */
extern "C"
os_thread_ret_t
DECLARE_THREAD(lock_wait_timeout_thread)(
/*=====================================*/
void* arg MY_ATTRIBUTE((unused)))
/* in: a dummy parameter required by
os_thread_create */
DECLARE_THREAD(lock_wait_timeout_thread)(void*)
{
int64_t sig_count = 0;
os_event_t event = lock_sys->timeout_event;
@@ -524,8 +520,6 @@ DECLARE_THREAD(lock_wait_timeout_thread)(
pfs_register_thread(srv_lock_timeout_thread_key);
#endif /* UNIV_PFS_THREAD */
lock_sys->timeout_thread_active = true;
do {
srv_slot_t* slot;

View File

@@ -2,7 +2,7 @@
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Google Inc.
Copyright (C) 2014, 2017, MariaDB Corporation. All Rights Reserved.
Copyright (c) 2014, 2017, MariaDB Corporation. All Rights Reserved.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -43,7 +43,7 @@ Created 12/9/1995 Heikki Tuuri
#include "mem0mem.h"
#include "buf0buf.h"
#include "buf0flu.h"
#include "srv0srv.h"
#include "lock0lock.h"
#include "log0recv.h"
#include "fil0fil.h"
#include "dict0boot.h"
@@ -135,6 +135,15 @@ the previous */
#define LOG_UNLOCK_NONE_FLUSHED_LOCK 1
#define LOG_UNLOCK_FLUSH_LOCK 2
/** Event to wake up log_scrub_thread */
os_event_t log_scrub_event;
/** Whether log_scrub_thread is active */
bool log_scrub_thread_active;
extern "C" UNIV_INTERN
os_thread_ret_t
DECLARE_THREAD(log_scrub_thread)(void*);
/******************************************************//**
Completes a checkpoint write i/o to a log file. */
static
@@ -860,6 +869,12 @@ log_init(void)
MONITOR_SET(MONITOR_LSN_CHECKPOINT_AGE,
log_sys->lsn - log_sys->last_checkpoint_lsn);
log_scrub_thread_active = !srv_read_only_mode && srv_scrub_log;
if (log_scrub_thread_active) {
log_scrub_event = os_event_create("log_scrub_event");
os_thread_create(log_scrub_thread, NULL, NULL);
}
}
/******************************************************************//**
@@ -2084,9 +2099,6 @@ logs_empty_and_mark_files_at_shutdown(void)
ulint count = 0;
ulint total_trx;
ulint pending_io;
enum srv_thread_type active_thd;
const char* thread_name;
dberr_t err = DB_SUCCESS;
ib::info() << "Starting shutdown...";
@@ -2101,29 +2113,19 @@ logs_empty_and_mark_files_at_shutdown(void)
srv_shutdown_state = SRV_SHUTDOWN_CLEANUP;
loop:
os_event_set(srv_buf_resize_event);
if (!srv_read_only_mode) {
os_event_set(srv_error_event);
os_event_set(srv_monitor_event);
os_event_set(srv_buf_dump_event);
os_event_set(lock_sys->timeout_event);
os_event_set(dict_stats_event);
}
os_thread_sleep(100000);
count++;
/* We need the monitor threads to stop before we proceed with
a shutdown. */
thread_name = srv_any_background_threads_are_active();
if (thread_name != NULL) {
/* Print a message every 60 seconds if we are waiting
for the monitor thread to exit. Master and worker
threads check will be done later. */
if (srv_print_verbose_log && count > 600) {
ib::info() << "Waiting for " << thread_name
<< " to exit";
count = 0;
}
goto loop;
}
/* Check that there are no longer transactions, except for
PREPARED ones. We need this wait even for the 'very fast'
shutdown, because the InnoDB layer may have committed or
@@ -2150,55 +2152,63 @@ loop:
goto loop;
}
/* Check that the background threads are suspended */
/* We need these threads to stop early in shutdown. */
const char* thread_name;
active_thd = srv_get_active_thread_type();
if (srv_error_monitor_active) {
thread_name = "srv_error_monitor_thread";
} else if (srv_monitor_active) {
thread_name = "srv_monitor_thread";
} else if (srv_buf_resize_thread_active) {
thread_name = "buf_resize_thread";
} else if (srv_dict_stats_thread_active) {
thread_name = "dict_stats_thread";
} else if (lock_sys->timeout_thread_active) {
thread_name = "lock_wait_timeout_thread";
} else if (srv_buf_dump_thread_active) {
thread_name = "buf_dump_thread";
} else {
thread_name = NULL;
}
if (active_thd != SRV_NONE) {
if (active_thd == SRV_PURGE) {
srv_purge_wakeup();
}
/* The srv_lock_timeout_thread, srv_error_monitor_thread
and srv_monitor_thread should already exit by now. The
only threads to be suspended are the master threads
and worker threads (purge threads). Print the thread
type if any of such threads not in suspended mode */
if (thread_name) {
ut_ad(!srv_read_only_mode);
wait_suspend_loop:
if (srv_print_verbose_log && count > 600) {
const char* thread_type = "<null>";
switch (active_thd) {
case SRV_NONE:
/* This shouldn't happen because we've
already checked for this case before
entering the if(). We handle it here
to avoid a compiler warning. */
ut_error;
case SRV_WORKER:
thread_type = "worker threads";
break;
case SRV_MASTER:
thread_type = "master thread";
break;
case SRV_PURGE:
thread_type = "purge thread";
break;
}
ib::info() << "Waiting for " << thread_type
<< " to be suspended";
ib::info() << "Waiting for " << thread_name
<< "to exit";
count = 0;
}
goto loop;
}
/* Check that the background threads are suspended */
switch (srv_get_active_thread_type()) {
case SRV_NONE:
srv_shutdown_state = SRV_SHUTDOWN_FLUSH_PHASE;
if (!srv_n_fil_crypt_threads_started) {
break;
}
os_event_set(fil_crypt_threads_event);
thread_name = "fil_crypt_thread";
goto wait_suspend_loop;
case SRV_PURGE:
srv_purge_wakeup();
thread_name = "purge thread";
goto wait_suspend_loop;
case SRV_MASTER:
thread_name = "master thread";
goto wait_suspend_loop;
case SRV_WORKER:
thread_name = "worker threads";
goto wait_suspend_loop;
}
/* At this point only page_cleaner should be active. We wait
here to let it complete the flushing of the buffer pools
before proceeding further. */
srv_shutdown_state = SRV_SHUTDOWN_FLUSH_PHASE;
count = 0;
while (buf_page_cleaner_is_active) {
++count;
@@ -2210,6 +2220,11 @@ loop:
}
}
if (log_scrub_thread_active) {
ut_ad(!srv_read_only_mode);
os_event_set(log_scrub_event);
}
log_mutex_enter();
const ulint n_write = log_sys->n_pending_checkpoint_writes;
const ulint n_flush = log_sys->n_pending_flushes;
@@ -2224,6 +2239,8 @@ loop:
goto loop;
}
ut_ad(!log_scrub_thread_active);
pending_io = buf_pool_check_no_pending_io();
if (pending_io) {
@@ -2254,73 +2271,48 @@ loop:
from the stamps if the previous shutdown was clean. */
log_buffer_flush_to_disk();
/* Check that the background threads stay suspended */
thread_name = srv_any_background_threads_are_active();
if (thread_name != NULL) {
ib::warn() << "Background thread "
<< thread_name << " woke up during"
" shutdown";
goto loop;
}
}
srv_shutdown_state = SRV_SHUTDOWN_LAST_PHASE;
fil_close_all_files();
thread_name = srv_any_background_threads_are_active();
ut_a(!thread_name);
return;
}
if (!srv_read_only_mode) {
log_make_checkpoint_at(LSN_MAX, TRUE);
}
log_mutex_enter();
log_mutex_enter();
lsn = log_sys->lsn;
lsn = log_sys->lsn;
ut_ad(lsn >= log_sys->last_checkpoint_lsn);
const bool lsn_changed = lsn != log_sys->last_checkpoint_lsn;
ut_ad(lsn >= log_sys->last_checkpoint_lsn);
log_mutex_exit();
log_mutex_exit();
if (lsn != log_sys->last_checkpoint_lsn) {
goto loop;
}
/* Check that the background threads stay suspended */
thread_name = srv_any_background_threads_are_active();
if (thread_name != NULL) {
ib::warn() << "Background thread " << thread_name << " woke up"
" during shutdown";
goto loop;
}
if (!srv_read_only_mode) {
fil_flush_file_spaces(FIL_TYPE_TABLESPACE);
fil_flush_file_spaces(FIL_TYPE_LOG);
}
/* The call fil_write_flushed_lsn() will bypass the buffer
pool: therefore it is essential that the buffer pool has been
completely flushed to disk! (We do not call fil_write... if the
'very fast' shutdown is enabled.) */
if (!buf_all_freed()) {
if (srv_print_verbose_log && count > 600) {
ib::info() << "Waiting for dirty buffer pages to be"
" flushed";
count = 0;
if (lsn_changed) {
goto loop;
}
goto loop;
fil_flush_file_spaces(FIL_TYPE_TABLESPACE);
fil_flush_file_spaces(FIL_TYPE_LOG);
/* The call fil_write_flushed_lsn_to_data_files() will
bypass the buffer pool: therefore it is essential that
the buffer pool has been completely flushed to disk! */
if (!buf_all_freed()) {
if (srv_print_verbose_log && count > 600) {
ib::info() << "Waiting for dirty buffer pages"
" to be flushed";
count = 0;
}
goto loop;
}
} else {
lsn = srv_start_lsn;
}
srv_shutdown_state = SRV_SHUTDOWN_LAST_PHASE;
@@ -2343,7 +2335,7 @@ loop:
srv_shutdown_lsn = lsn;
if (!srv_read_only_mode) {
err = fil_write_flushed_lsn(lsn);
dberr_t err = fil_write_flushed_lsn(lsn);
if (err != DB_SUCCESS) {
ib::error() << "Writing flushed lsn " << lsn
@@ -2504,6 +2496,10 @@ log_shutdown(void)
mutex_free(&log_sys->write_mutex);
mutex_free(&log_sys->log_flush_order_mutex);
if (!srv_read_only_mode && srv_scrub_log) {
os_event_destroy(log_scrub_event);
}
recv_sys_close();
}
@@ -2521,11 +2517,6 @@ log_mem_free(void)
}
}
/** Event to wake up the log scrub thread */
UNIV_INTERN os_event_t log_scrub_event = NULL;
UNIV_INTERN ibool srv_log_scrub_thread_active = FALSE;
/******************************************************//**
Pads the current log block full with dummy log records. Used in producing
consistent archived log files and scrubbing redo log. */
@@ -2597,17 +2588,11 @@ sleeps again.
@return this function does not return, it calls os_thread_exit() */
extern "C" UNIV_INTERN
os_thread_ret_t
DECLARE_THREAD(log_scrub_thread)(
/*===============================*/
void* arg __attribute__((unused))) /*!< in: a dummy parameter
required by os_thread_create */
DECLARE_THREAD(log_scrub_thread)(void*)
{
ut_ad(!srv_read_only_mode);
srv_log_scrub_thread_active = TRUE;
while(srv_shutdown_state == SRV_SHUTDOWN_NONE)
{
while (srv_shutdown_state < SRV_SHUTDOWN_FLUSH_PHASE) {
/* log scrubbing interval in µs. */
ulonglong interval = 1000*1000*512/innodb_scrub_log_speed;
@@ -2618,7 +2603,7 @@ DECLARE_THREAD(log_scrub_thread)(
os_event_reset(log_scrub_event);
}
srv_log_scrub_thread_active = FALSE;
log_scrub_thread_active = false;
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit and not use return() to exit. */

View File

@@ -3,7 +3,7 @@
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2016, MariaDB Corporation.
Copyright (c) 2013, 2017, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -53,7 +53,6 @@ Created 10/8/1995 Heikki Tuuri
#include "buf0lru.h"
#include "dict0boot.h"
#include "dict0load.h"
#include "dict0stats_bg.h"
#include "fsp0sysspace.h"
#include "ibuf0ibuf.h"
#include "lock0lock.h"
@@ -90,17 +89,13 @@ UNIV_INTERN ulong srv_fatal_semaphore_wait_threshold = DEFAULT_SRV_FATAL_SEMAPH
in microseconds, in order to reduce the lagging of the purge thread. */
ulint srv_dml_needed_delay = 0;
ibool srv_monitor_active = FALSE;
ibool srv_error_monitor_active = FALSE;
bool srv_monitor_active;
bool srv_error_monitor_active;
bool srv_buf_dump_thread_active;
bool srv_dict_stats_thread_active;
bool srv_buf_resize_thread_active;
ibool srv_buf_dump_thread_active = FALSE;
bool srv_buf_resize_thread_active = false;
UNIV_INTERN ibool srv_log_scrub_active = FALSE;
UNIV_INTERN my_bool srv_scrub_log = FALSE;
ibool srv_dict_stats_thread_active = FALSE;
my_bool srv_scrub_log;
const char* srv_main_thread_op_info = "";
@@ -1715,11 +1710,7 @@ A thread which prints the info output by various InnoDB monitors.
@return a dummy parameter */
extern "C"
os_thread_ret_t
DECLARE_THREAD(srv_monitor_thread)(
/*===============================*/
void* arg MY_ATTRIBUTE((unused)))
/*!< in: a dummy parameter required by
os_thread_create */
DECLARE_THREAD(srv_monitor_thread)(void*)
{
int64_t sig_count;
double time_elapsed;
@@ -1740,9 +1731,7 @@ DECLARE_THREAD(srv_monitor_thread)(
#ifdef UNIV_PFS_THREAD
pfs_register_thread(srv_monitor_thread_key);
#endif /* UNIV_PFS_THREAD */
srv_monitor_active = TRUE;
UT_NOT_USED(arg);
srv_last_monitor_time = ut_time();
last_table_monitor_time = ut_time();
last_tablespace_monitor_time = ut_time();
@@ -1875,7 +1864,7 @@ loop:
goto loop;
exit_func:
srv_monitor_active = FALSE;
srv_monitor_active = false;
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit and not use return() to exit. */
@@ -1891,11 +1880,7 @@ too long. These can be used to track bugs which cause hangs.
@return a dummy parameter */
extern "C"
os_thread_ret_t
DECLARE_THREAD(srv_error_monitor_thread)(
/*=====================================*/
void* arg MY_ATTRIBUTE((unused)))
/*!< in: a dummy parameter required by
os_thread_create */
DECLARE_THREAD(srv_error_monitor_thread)(void*)
{
/* number of successive fatal timeouts observed */
ulint fatal_cnt = 0;
@@ -1921,7 +1906,6 @@ DECLARE_THREAD(srv_error_monitor_thread)(
#ifdef UNIV_PFS_THREAD
pfs_register_thread(srv_error_monitor_thread_key);
#endif /* UNIV_PFS_THREAD */
srv_error_monitor_active = TRUE;
loop:
/* Try to track a strange bug reported by Harald Fuchs and others,
@@ -1994,7 +1978,7 @@ loop:
goto loop;
}
srv_error_monitor_active = FALSE;
srv_error_monitor_active = false;
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit and not use return() to exit. */
@@ -2051,52 +2035,6 @@ srv_get_active_thread_type(void)
return(ret);
}
/**********************************************************************//**
Check whether any background thread are active. If so print which thread
is active. Send the threads wakeup signal.
@return name of thread that is active or NULL */
const char*
srv_any_background_threads_are_active(void)
/*=======================================*/
{
const char* thread_active = NULL;
if (srv_read_only_mode) {
if (srv_buf_resize_thread_active) {
thread_active = "buf_resize_thread";
}
os_event_set(srv_buf_resize_event);
return(thread_active);
} else if (srv_error_monitor_active) {
thread_active = "srv_error_monitor_thread";
} else if (lock_sys->timeout_thread_active) {
thread_active = "srv_lock_timeout thread";
} else if (srv_monitor_active) {
thread_active = "srv_monitor_thread";
} else if (srv_buf_dump_thread_active) {
thread_active = "buf_dump_thread";
} else if (srv_buf_resize_thread_active) {
thread_active = "buf_resize_thread";
} else if (srv_dict_stats_thread_active) {
thread_active = "dict_stats_thread";
} else if (srv_scrub_log && srv_log_scrub_thread_active) {
thread_active = "log_scrub_thread";
}
os_event_set(srv_error_event);
os_event_set(srv_monitor_event);
os_event_set(srv_buf_dump_event);
os_event_set(lock_sys->timeout_event);
os_event_set(dict_stats_event);
os_event_set(srv_buf_resize_event);
if (srv_scrub_log) {
os_event_set(log_scrub_event);
}
return(thread_active);
}
/*******************************************************************//**
Tells the InnoDB server that there has been activity in the database
and wakes up the master thread if it is suspended (not sleeping). Used

View File

@@ -3,7 +3,7 @@
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2016, MariaDB Corporation
Copyright (c) 2013, 2017, MariaDB Corporation
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -1209,13 +1209,11 @@ srv_start_state_is_set(
/**
Shutdown all background threads created by InnoDB. */
static
void
srv_shutdown_all_bg_threads()
{
ulint i;
srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS;
fil_crypt_threads_end();
if (!srv_start_state) {
return;
@@ -1224,7 +1222,7 @@ srv_shutdown_all_bg_threads()
/* All threads end up waiting for certain events. Put those events
to the signaled state. Then the threads will exit themselves after
os_event_wait(). */
for (i = 0; i < 1000; i++) {
for (uint i = 0; i < 1000; ++i) {
/* NOTE: IF YOU CREATE THREADS IN INNODB, YOU MUST EXIT THEM
HERE OR EARLIER */
@@ -1247,6 +1245,14 @@ srv_shutdown_all_bg_threads()
/* d. Wakeup purge threads. */
srv_purge_wakeup();
}
if (srv_n_fil_crypt_threads_started) {
os_event_set(fil_crypt_threads_event);
}
if (log_scrub_thread_active) {
os_event_set(log_scrub_event);
}
}
if (srv_start_state_is_set(SRV_START_STATE_IO)) {
@@ -1277,26 +1283,20 @@ srv_shutdown_all_bg_threads()
os_aio_wake_all_threads_at_shutdown();
}
bool active = os_thread_active();
const bool active = os_thread_active();
os_thread_sleep(100000);
if (!active) {
break;
srv_start_state = SRV_START_STATE_NONE;
return;
}
}
if (i == 1000) {
ib::warn() << os_thread_count << " threads created by InnoDB"
" had not exited at shutdown!";
#ifdef UNIV_DEBUG
os_aio_print_pending_io(stderr);
ut_ad(0);
#endif /* UNIV_DEBUG */
} else {
/* Reset the start state. */
srv_start_state = SRV_START_STATE_NONE;
}
ib::warn() << os_thread_count << " threads created by InnoDB"
" had not exited at shutdown!";
ut_d(os_aio_print_pending_io(stderr));
ut_ad(0);
}
#ifdef UNIV_DEBUG
@@ -2107,11 +2107,6 @@ files_checked:
dict_stats_thread_init();
}
if (!srv_read_only_mode && srv_scrub_log) {
/* TODO(minliz): have/use log_scrub_thread_init() instead? */
log_scrub_event = os_event_create(0);
}
trx_sys_file_format_init();
trx_sys_create();
@@ -2462,14 +2457,17 @@ files_checked:
lock_wait_timeout_thread,
NULL, thread_ids + 2 + SRV_MAX_N_IO_THREADS);
thread_started[2 + SRV_MAX_N_IO_THREADS] = true;
lock_sys->timeout_thread_active = true;
/* Create the thread which warns of long semaphore waits */
srv_error_monitor_active = true;
thread_handles[3 + SRV_MAX_N_IO_THREADS] = os_thread_create(
srv_error_monitor_thread,
NULL, thread_ids + 3 + SRV_MAX_N_IO_THREADS);
thread_started[3 + SRV_MAX_N_IO_THREADS] = true;
/* Create the thread which prints InnoDB monitor info */
srv_monitor_active = true;
thread_handles[4 + SRV_MAX_N_IO_THREADS] = os_thread_create(
srv_monitor_thread,
NULL, thread_ids + 4 + SRV_MAX_N_IO_THREADS);
@@ -2671,6 +2669,8 @@ files_checked:
/* Create the buffer pool dump/load thread */
buf_dump_thread_handle=
os_thread_create(buf_dump_thread, NULL, NULL);
srv_buf_dump_thread_active = true;
buf_dump_thread_started = true;
#ifdef WITH_WSREP
} else {
@@ -2681,21 +2681,19 @@ files_checked:
#endif /* WITH_WSREP */
/* Create the dict stats gathering thread */
dict_stats_thread_handle = os_thread_create(dict_stats_thread, NULL, NULL);
dict_stats_thread_handle = os_thread_create(
dict_stats_thread, NULL, NULL);
srv_dict_stats_thread_active = true;
dict_stats_thread_started = true;
/* Create the thread that will optimize the FTS sub-system. */
fts_optimize_init();
srv_start_state_set(SRV_START_STATE_STAT);
/* Create the log scrub thread */
if (srv_scrub_log) {
os_thread_create(log_scrub_thread, NULL, NULL);
}
}
/* Create the buffer pool resize thread */
srv_buf_resize_thread_active = true;
os_thread_create(buf_resize_thread, NULL, NULL);
/* Init data for datafile scrub threads */
@@ -2805,15 +2803,9 @@ innobase_shutdown_for_mysql(void)
if (!srv_read_only_mode) {
dict_stats_thread_deinit();
if (srv_scrub_log) {
/* TODO(minliz): have/use log_scrub_thread_deinit() instead? */
os_event_destroy(log_scrub_event);
log_scrub_event = NULL;
}
fil_crypt_threads_cleanup();
}
fil_crypt_threads_cleanup();
/* Cleanup data for datafile scrubbing */
btr_scrub_cleanup();

View File

@@ -395,19 +395,33 @@ trx_purge_add_update_undo_to_history(
}
}
/**********************************************************************//**
Frees an undo log segment which is in the history list. Cuts the end of the
history list at the youngest undo log in this segment. */
/** Remove undo log header from the history list.
@param[in,out] rseg_hdr rollback segment header
@param[in] log_hdr undo log segment header
@param[in,out] mtr mini transaction. */
static
void
trx_purge_remove_log_hdr(
trx_rsegf_t* rseg_hdr,
trx_ulogf_t* log_hdr,
mtr_t* mtr)
{
flst_remove(rseg_hdr + TRX_RSEG_HISTORY,
log_hdr + TRX_UNDO_HISTORY_NODE, mtr);
my_atomic_addlint(&trx_sys->rseg_history_len, -1);
}
/** Frees an undo log segment which is in the history list. Removes the
undo log hdr from the history list.
@param[in,out] rseg rollback segment
@param[in] hdr_addr file address of log_hdr
@param[in] noredo skip redo logging. */
static
void
trx_purge_free_segment(
/*===================*/
trx_rseg_t* rseg, /*!< in: rollback segment */
fil_addr_t hdr_addr, /*!< in: the file address of log_hdr */
ulint n_removed_logs, /*!< in: count of how many undo logs we
will cut off from the end of the
history list */
bool noredo) /*!< in: skip redo logging */
trx_rseg_t* rseg,
fil_addr_t hdr_addr,
bool noredo)
{
mtr_t mtr;
trx_rsegf_t* rseg_hdr;
@@ -473,10 +487,7 @@ trx_purge_free_segment(
history list: otherwise, in case of a database crash, the segment
could become inaccessible garbage in the file space. */
flst_cut_end(rseg_hdr + TRX_RSEG_HISTORY,
log_hdr + TRX_UNDO_HISTORY_NODE, n_removed_logs, &mtr);
my_atomic_addlint(&trx_sys->rseg_history_len, -n_removed_logs);
trx_purge_remove_log_hdr(rseg_hdr, log_hdr, &mtr);
do {
@@ -518,7 +529,6 @@ trx_purge_truncate_rseg_history(
page_t* undo_page;
trx_ulogf_t* log_hdr;
trx_usegf_t* seg_hdr;
ulint n_removed_logs = 0;
mtr_t mtr;
trx_id_t undo_trx_no;
const bool noredo = trx_sys_is_noredo_rseg_slot(
@@ -565,13 +575,6 @@ loop:
hdr_addr.boffset, limit->undo_no);
}
my_atomic_addlint(
&trx_sys->rseg_history_len, -n_removed_logs);
flst_truncate_end(rseg_hdr + TRX_RSEG_HISTORY,
log_hdr + TRX_UNDO_HISTORY_NODE,
n_removed_logs, &mtr);
mutex_exit(&(rseg->mutex));
mtr_commit(&mtr);
@@ -580,7 +583,6 @@ loop:
prev_hdr_addr = trx_purge_get_log_from_hist(
flst_get_prev_addr(log_hdr + TRX_UNDO_HISTORY_NODE, &mtr));
n_removed_logs++;
seg_hdr = undo_page + TRX_UNDO_SEG_HDR;
@@ -592,10 +594,13 @@ loop:
mutex_exit(&(rseg->mutex));
mtr_commit(&mtr);
trx_purge_free_segment(rseg, hdr_addr, n_removed_logs, noredo);
n_removed_logs = 0;
/* calls the trx_purge_remove_log_hdr()
inside trx_purge_free_segment(). */
trx_purge_free_segment(rseg, hdr_addr, noredo);
} else {
/* Remove the log hdr from the rseg history. */
trx_purge_remove_log_hdr(rseg_hdr, log_hdr, &mtr);
mutex_exit(&(rseg->mutex));
mtr_commit(&mtr);
}

View File

@@ -2099,7 +2099,7 @@ trx_commit_in_memory(
trx->dict_operation = TRX_DICT_OP_NONE;
#ifdef WITH_WSREP
if (wsrep_on(trx->mysql_thd)) {
if (trx->mysql_thd && wsrep_on(trx->mysql_thd)) {
trx->lock.was_chosen_as_deadlock_victim = FALSE;
}
#endif

View File

@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
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
@@ -682,15 +683,10 @@ again.
@return this function does not return, it calls os_thread_exit() */
extern "C" UNIV_INTERN
os_thread_ret_t
DECLARE_THREAD(buf_dump_thread)(
/*============================*/
void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter
required by os_thread_create */
DECLARE_THREAD(buf_dump_thread)(void*)
{
ut_ad(!srv_read_only_mode);
srv_buf_dump_thread_active = TRUE;
buf_dump_status(STATUS_INFO, "Dumping buffer pool(s) not yet started");
buf_load_status(STATUS_INFO, "Loading buffer pool(s) not yet started");
@@ -720,7 +716,7 @@ DECLARE_THREAD(buf_dump_thread)(
keep going even if we are in a shutdown state */);
}
srv_buf_dump_thread_active = FALSE;
srv_buf_dump_thread_active = false;
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit and not use return() to exit. */

View File

@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2016, MariaDB Corporation.
Copyright (c) 2016, 2017, 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
@@ -273,10 +273,6 @@ dict_boot(void)
ut_ad(DICT_NUM_FIELDS__SYS_FOREIGN_FOR_NAME == 2);
ut_ad(DICT_NUM_COLS__SYS_FOREIGN_COLS == 4);
ut_ad(DICT_NUM_FIELDS__SYS_FOREIGN_COLS == 6);
ut_ad(DICT_NUM_COLS__SYS_ZIP_DICT == 3);
ut_ad(DICT_NUM_FIELDS__SYS_ZIP_DICT == 5);
ut_ad(DICT_NUM_COLS__SYS_ZIP_DICT_COLS == 3);
ut_ad(DICT_NUM_FIELDS__SYS_ZIP_DICT_COLS == 5);
mtr_start(&mtr);

View File

@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 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
@@ -1936,135 +1937,6 @@ dict_create_or_check_sys_tablespace(void)
return(err);
}
/** Creates the zip_dict system table inside InnoDB
at server bootstrap or server start if it is not found or is
not of the right form.
@return DB_SUCCESS or error code */
UNIV_INTERN
dberr_t
dict_create_or_check_sys_zip_dict(void)
{
trx_t* trx;
my_bool srv_file_per_table_backup;
dberr_t err;
dberr_t sys_zip_dict_err;
dberr_t sys_zip_dict_cols_err;
ut_a(srv_get_active_thread_type() == SRV_NONE);
/* Note: The master thread has not been started at this point. */
sys_zip_dict_err = dict_check_if_system_table_exists(
"SYS_ZIP_DICT", DICT_NUM_FIELDS__SYS_ZIP_DICT + 1, 2);
sys_zip_dict_cols_err = dict_check_if_system_table_exists(
"SYS_ZIP_DICT_COLS", DICT_NUM_FIELDS__SYS_ZIP_DICT_COLS + 1,
1);
if (sys_zip_dict_err == DB_SUCCESS &&
sys_zip_dict_cols_err == DB_SUCCESS)
return (DB_SUCCESS);
trx = trx_allocate_for_mysql();
trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
trx->op_info = "creating zip_dict and zip_dict_cols sys tables";
row_mysql_lock_data_dictionary(trx);
/* Check which incomplete table definition to drop. */
if (sys_zip_dict_err == DB_CORRUPTION) {
ib_logf(IB_LOG_LEVEL_WARN,
"Dropping incompletely created "
"SYS_ZIP_DICT table.");
row_drop_table_for_mysql("SYS_ZIP_DICT", trx, TRUE, TRUE);
}
if (sys_zip_dict_cols_err == DB_CORRUPTION) {
ib_logf(IB_LOG_LEVEL_WARN,
"Dropping incompletely created "
"SYS_ZIP_DICT_COLS table.");
row_drop_table_for_mysql("SYS_ZIP_DICT_COLS", trx, TRUE, TRUE);
}
ib_logf(IB_LOG_LEVEL_INFO,
"Creating zip_dict and zip_dict_cols system tables.");
/* We always want SYSTEM tables to be created inside the system
tablespace. */
srv_file_per_table_backup = srv_file_per_table;
srv_file_per_table = 0;
err = que_eval_sql(
NULL,
"PROCEDURE CREATE_SYS_ZIP_DICT_PROC () IS\n"
"BEGIN\n"
"CREATE TABLE SYS_ZIP_DICT(\n"
" ID INT UNSIGNED NOT NULL,\n"
" NAME CHAR("
STRINGIFY_ARG(ZIP_DICT_MAX_NAME_LENGTH)
") NOT NULL,\n"
" DATA BLOB NOT NULL\n"
");\n"
"CREATE UNIQUE CLUSTERED INDEX SYS_ZIP_DICT_ID"
" ON SYS_ZIP_DICT (ID);\n"
"CREATE UNIQUE INDEX SYS_ZIP_DICT_NAME"
" ON SYS_ZIP_DICT (NAME);\n"
"CREATE TABLE SYS_ZIP_DICT_COLS(\n"
" TABLE_ID INT UNSIGNED NOT NULL,\n"
" COLUMN_POS INT UNSIGNED NOT NULL,\n"
" DICT_ID INT UNSIGNED NOT NULL\n"
");\n"
"CREATE UNIQUE CLUSTERED INDEX SYS_ZIP_DICT_COLS_COMPOSITE"
" ON SYS_ZIP_DICT_COLS (TABLE_ID, COLUMN_POS);\n"
"END;\n",
FALSE, trx);
if (err != DB_SUCCESS) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Creation of SYS_ZIP_DICT and SYS_ZIP_DICT_COLS"
"has failed with error %lu. Tablespace is full. "
"Dropping incompletely created tables.",
(ulong) err);
ut_a(err == DB_OUT_OF_FILE_SPACE
|| err == DB_TOO_MANY_CONCURRENT_TRXS);
row_drop_table_for_mysql("SYS_ZIP_DICT", trx, TRUE, TRUE);
row_drop_table_for_mysql("SYS_ZIP_DICT_COLS", trx, TRUE, TRUE);
if (err == DB_OUT_OF_FILE_SPACE) {
err = DB_MUST_GET_MORE_FILE_SPACE;
}
}
trx_commit_for_mysql(trx);
row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
srv_file_per_table = srv_file_per_table_backup;
if (err == DB_SUCCESS) {
ib_logf(IB_LOG_LEVEL_INFO,
"zip_dict and zip_dict_cols system tables created.");
}
/* 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_zip_dict_err = dict_check_if_system_table_exists(
"SYS_ZIP_DICT", DICT_NUM_FIELDS__SYS_ZIP_DICT + 1, 2);
ut_a(sys_zip_dict_err == DB_SUCCESS);
sys_zip_dict_cols_err = dict_check_if_system_table_exists(
"SYS_ZIP_DICT_COLS",
DICT_NUM_FIELDS__SYS_ZIP_DICT_COLS + 1, 1);
ut_a(sys_zip_dict_cols_err == DB_SUCCESS);
return(err);
}
/********************************************************************//**
Add a single tablespace definition to the data dictionary tables in the
database.
@@ -2118,456 +1990,3 @@ dict_create_add_tablespace_to_dictionary(
return(error);
}
/** Add a single compression dictionary definition to the SYS_ZIP_DICT
InnoDB system table.
@return error code or DB_SUCCESS */
UNIV_INTERN
dberr_t
dict_create_add_zip_dict(
const char* name, /*!< in: dict name */
ulint name_len, /*!< in: dict name length */
const char* data, /*!< in: dict data */
ulint data_len, /*!< in: dict data length */
trx_t* trx) /*!< in/out: transaction */
{
ut_ad(name);
ut_ad(data);
pars_info_t* info = pars_info_create();
pars_info_add_literal(info, "name", name, name_len,
DATA_VARCHAR, DATA_ENGLISH);
pars_info_add_literal(info, "data", data, data_len,
DATA_BLOB, DATA_BINARY_TYPE | DATA_NOT_NULL);
dberr_t error = que_eval_sql(info,
"PROCEDURE P () IS\n"
" max_id INT;\n"
"DECLARE CURSOR cur IS\n"
" SELECT ID FROM SYS_ZIP_DICT\n"
" ORDER BY ID DESC;\n"
"BEGIN\n"
" max_id := 0;\n"
" OPEN cur;\n"
" FETCH cur INTO max_id;\n"
" IF (cur % NOTFOUND) THEN\n"
" max_id := 0;\n"
" END IF;\n"
" CLOSE cur;\n"
" INSERT INTO SYS_ZIP_DICT VALUES"
" (max_id + 1, :name, :data);\n"
"END;\n",
FALSE, trx);
return error;
}
/** Fetch callback, just stores extracted zip_dict id in the external
variable.
@return TRUE if all OK */
static
ibool
dict_create_extract_int_aux(
void* row, /*!< in: sel_node_t* */
void* user_arg) /*!< in: int32 id */
{
sel_node_t* node = static_cast<sel_node_t*>(row);
dfield_t* dfield = que_node_get_val(node->select_list);
dtype_t* type = dfield_get_type(dfield);
ulint len = dfield_get_len(dfield);
ut_a(dtype_get_mtype(type) == DATA_INT);
ut_a(len == sizeof(ib_uint32_t));
memcpy(user_arg, dfield_get_data(dfield), sizeof(ib_uint32_t));
return(TRUE);
}
/** Add a single compression dictionary reference to the SYS_ZIP_DICT_COLS
InnoDB system table.
@return error code or DB_SUCCESS */
UNIV_INTERN
dberr_t
dict_create_add_zip_dict_reference(
ulint table_id, /*!< in: table id */
ulint column_pos, /*!< in: column position */
ulint dict_id, /*!< in: dict id */
trx_t* trx) /*!< in/out: transaction */
{
pars_info_t* info = pars_info_create();
pars_info_add_int4_literal(info, "table_id", table_id);
pars_info_add_int4_literal(info, "column_pos", column_pos);
pars_info_add_int4_literal(info, "dict_id", dict_id);
dberr_t error = que_eval_sql(info,
"PROCEDURE P () IS\n"
"BEGIN\n"
" INSERT INTO SYS_ZIP_DICT_COLS VALUES"
" (:table_id, :column_pos, :dict_id);\n"
"END;\n",
FALSE, trx);
return error;
}
/** Get a single compression dictionary id for the given
(table id, column pos) pair.
@return error code or DB_SUCCESS */
UNIV_INTERN
dberr_t
dict_create_get_zip_dict_id_by_reference(
ulint table_id, /*!< in: table id */
ulint column_pos, /*!< in: column position */
ulint* dict_id, /*!< out: dict id */
trx_t* trx) /*!< in/out: transaction */
{
ut_ad(dict_id);
pars_info_t* info = pars_info_create();
ib_uint32_t dict_id_buf;
mach_write_to_4(reinterpret_cast<byte*>(&dict_id_buf ),
ULINT32_UNDEFINED);
pars_info_add_int4_literal(info, "table_id", table_id);
pars_info_add_int4_literal(info, "column_pos", column_pos);
pars_info_bind_function(
info, "my_func", dict_create_extract_int_aux, &dict_id_buf);
dberr_t error = que_eval_sql(info,
"PROCEDURE P () IS\n"
"DECLARE FUNCTION my_func;\n"
"DECLARE CURSOR cur IS\n"
" SELECT DICT_ID FROM SYS_ZIP_DICT_COLS\n"
" WHERE TABLE_ID = :table_id AND\n"
" COLUMN_POS = :column_pos;\n"
"BEGIN\n"
" OPEN cur;\n"
" FETCH cur INTO my_func();\n"
" CLOSE cur;\n"
"END;\n",
FALSE, trx);
if (error == DB_SUCCESS) {
ib_uint32_t local_dict_id = mach_read_from_4(
reinterpret_cast<const byte*>(&dict_id_buf));
if (local_dict_id == ULINT32_UNDEFINED)
error = DB_RECORD_NOT_FOUND;
else
*dict_id = local_dict_id;
}
return error;
}
/** Get compression dictionary id for the given name.
@return error code or DB_SUCCESS */
UNIV_INTERN
dberr_t
dict_create_get_zip_dict_id_by_name(
const char* dict_name, /*!< in: dict name */
ulint dict_name_len, /*!< in: dict name length */
ulint* dict_id, /*!< out: dict id */
trx_t* trx) /*!< in/out: transaction */
{
ut_ad(dict_name);
ut_ad(dict_name_len);
ut_ad(dict_id);
pars_info_t* info = pars_info_create();
pars_info_add_literal(info, "dict_name", dict_name, dict_name_len,
DATA_VARCHAR, DATA_ENGLISH);
ib_uint32_t dict_id_buf;
mach_write_to_4(reinterpret_cast<byte*>(&dict_id_buf),
ULINT32_UNDEFINED);
pars_info_bind_function(
info, "my_func", dict_create_extract_int_aux, &dict_id_buf);
dberr_t error = que_eval_sql(info,
"PROCEDURE P () IS\n"
"DECLARE FUNCTION my_func;\n"
"DECLARE CURSOR cur IS\n"
" SELECT ID FROM SYS_ZIP_DICT\n"
" WHERE NAME = :dict_name;\n"
"BEGIN\n"
" OPEN cur;\n"
" FETCH cur INTO my_func();\n"
" CLOSE cur;\n"
"END;\n",
FALSE, trx);
if (error == DB_SUCCESS) {
ib_uint32_t local_dict_id = mach_read_from_4(
reinterpret_cast<const byte*>(&dict_id_buf));
if (local_dict_id == ULINT32_UNDEFINED)
error = DB_RECORD_NOT_FOUND;
else
*dict_id = local_dict_id;
}
return error;
}
/** Auxiliary enum used to indicate zip dict data extraction result code */
enum zip_dict_info_aux_code {
zip_dict_info_success, /*!< success */
zip_dict_info_not_found, /*!< zip dict record not found */
zip_dict_info_oom, /*!< out of memory */
zip_dict_info_corrupted_name, /*!< corrupted zip dict name */
zip_dict_info_corrupted_data /*!< corrupted zip dict data */
};
/** Auxiliary struct used to return zip dict info aling with result code */
struct zip_dict_info_aux {
LEX_STRING name; /*!< zip dict name */
LEX_STRING data; /*!< zip dict data */
int code; /*!< result code (0 - success) */
};
/** Fetch callback, just stores extracted zip_dict data in the external
variable.
@return always returns TRUE */
static
ibool
dict_create_get_zip_dict_info_by_id_aux(
void* row, /*!< in: sel_node_t* */
void* user_arg) /*!< in: pointer to zip_dict_info_aux* */
{
sel_node_t* node = static_cast<sel_node_t*>(row);
zip_dict_info_aux* result =
static_cast<zip_dict_info_aux*>(user_arg);
result->code = zip_dict_info_success;
result->name.str = 0;
result->name.length = 0;
result->data.str = 0;
result->data.length = 0;
/* NAME field */
que_node_t* exp = node->select_list;
ut_a(exp != 0);
dfield_t* dfield = que_node_get_val(exp);
dtype_t* type = dfield_get_type(dfield);
ut_a(dtype_get_mtype(type) == DATA_VARCHAR);
ulint len = dfield_get_len(dfield);
void* data = dfield_get_data(dfield);
if (len == UNIV_SQL_NULL) {
result->code = zip_dict_info_corrupted_name;
}
else {
result->name.str =
static_cast<char*>(my_malloc(len + 1, MYF(0)));
if (result->name.str == 0) {
result->code = zip_dict_info_oom;
}
else {
memcpy(result->name.str, data, len);
result->name.str[len] = '\0';
result->name.length = len;
}
}
/* DATA field */
exp = que_node_get_next(exp);
ut_a(exp != 0);
dfield = que_node_get_val(exp);
type = dfield_get_type(dfield);
ut_a(dtype_get_mtype(type) == DATA_BLOB);
len = dfield_get_len(dfield);
data = dfield_get_data(dfield);
if (len == UNIV_SQL_NULL) {
result->code = zip_dict_info_corrupted_data;
}
else {
result->data.str =
static_cast<char*>(my_malloc(
len == 0 ? 1 : len, MYF(0)));
if (result->data.str == 0) {
result->code = zip_dict_info_oom;
}
else {
memcpy(result->data.str, data, len);
result->data.length = len;
}
}
ut_ad(que_node_get_next(exp) == 0);
if (result->code != zip_dict_info_success) {
if (result->name.str == 0) {
mem_free(result->name.str);
result->name.str = 0;
result->name.length = 0;
}
if (result->data.str == 0) {
mem_free(result->data.str);
result->data.str = 0;
result->data.length = 0;
}
}
return TRUE;
}
/** Get compression dictionary info (name and data) for the given id.
Allocates memory for name and data on success.
Must be freed with mem_free().
@return error code or DB_SUCCESS */
UNIV_INTERN
dberr_t
dict_create_get_zip_dict_info_by_id(
ulint dict_id, /*!< in: dict id */
char** name, /*!< out: dict name */
ulint* name_len, /*!< out: dict name length*/
char** data, /*!< out: dict data */
ulint* data_len, /*!< out: dict data length*/
trx_t* trx) /*!< in/out: transaction */
{
ut_ad(name);
ut_ad(data);
zip_dict_info_aux rec;
rec.code = zip_dict_info_not_found;
pars_info_t* info = pars_info_create();
pars_info_add_int4_literal(info, "id", dict_id);
pars_info_bind_function(
info, "my_func", dict_create_get_zip_dict_info_by_id_aux,
&rec);
dberr_t error = que_eval_sql(info,
"PROCEDURE P () IS\n"
"DECLARE FUNCTION my_func;\n"
"DECLARE CURSOR cur IS\n"
" SELECT NAME, DATA FROM SYS_ZIP_DICT\n"
" WHERE ID = :id;\n"
"BEGIN\n"
" OPEN cur;\n"
" FETCH cur INTO my_func();\n"
" CLOSE cur;\n"
"END;\n",
FALSE, trx);
if (error == DB_SUCCESS) {
switch (rec.code) {
case zip_dict_info_success:
*name = rec.name.str;
*name_len = rec.name.length;
*data = rec.data.str;
*data_len = rec.data.length;
break;
case zip_dict_info_not_found:
error = DB_RECORD_NOT_FOUND;
break;
case zip_dict_info_oom:
error = DB_OUT_OF_MEMORY;
break;
case zip_dict_info_corrupted_name:
case zip_dict_info_corrupted_data:
error = DB_INVALID_NULL;
break;
default:
ut_error;
}
}
return error;
}
/** Remove a single compression dictionary from the data dictionary
tables in the database.
@return error code or DB_SUCCESS */
UNIV_INTERN
dberr_t
dict_create_remove_zip_dict(
const char* name, /*!< in: dict name */
ulint name_len, /*!< in: dict name length */
trx_t* trx) /*!< in/out: transaction */
{
ut_ad(name);
pars_info_t* info = pars_info_create();
ib_uint32_t dict_id_buf;
mach_write_to_4(reinterpret_cast<byte*>(&dict_id_buf),
ULINT32_UNDEFINED);
ib_uint32_t counter_buf;
mach_write_to_4(reinterpret_cast<byte*>(&counter_buf),
ULINT32_UNDEFINED);
pars_info_add_literal(info, "name", name, name_len,
DATA_VARCHAR, DATA_ENGLISH);
pars_info_bind_int4_literal(info, "dict_id", &dict_id_buf);
pars_info_bind_function(info, "find_dict_func",
dict_create_extract_int_aux, &dict_id_buf);
pars_info_bind_function(info, "count_func",
dict_create_extract_int_aux, &counter_buf);
dberr_t error = que_eval_sql(info,
"PROCEDURE P () IS\n"
"DECLARE FUNCTION find_dict_func;\n"
"DECLARE FUNCTION count_func;\n"
"DECLARE CURSOR dict_cur IS\n"
" SELECT ID FROM SYS_ZIP_DICT\n"
" WHERE NAME = :name\n"
" FOR UPDATE;\n"
"DECLARE CURSOR ref_cur IS\n"
" SELECT 1 FROM SYS_ZIP_DICT_COLS\n"
" WHERE DICT_ID = :dict_id;\n"
"BEGIN\n"
" OPEN dict_cur;\n"
" FETCH dict_cur INTO find_dict_func();\n"
" IF NOT (SQL % NOTFOUND) THEN\n"
" OPEN ref_cur;\n"
" FETCH ref_cur INTO count_func();\n"
" IF SQL % NOTFOUND THEN\n"
" DELETE FROM SYS_ZIP_DICT WHERE CURRENT OF dict_cur;\n"
" END IF;\n"
" CLOSE ref_cur;\n"
" END IF;\n"
" CLOSE dict_cur;\n"
"END;\n",
FALSE, trx);
if (error == DB_SUCCESS) {
ib_uint32_t local_dict_id = mach_read_from_4(
reinterpret_cast<const byte*>(&dict_id_buf));
if (local_dict_id == ULINT32_UNDEFINED) {
error = DB_RECORD_NOT_FOUND;
}
else {
ib_uint32_t local_counter = mach_read_from_4(
reinterpret_cast<const byte*>(&counter_buf));
if (local_counter != ULINT32_UNDEFINED)
error = DB_ROW_IS_REFERENCED;
}
}
return error;
}
/** Remove all compression dictionary references for the given table ID from
the data dictionary tables in the database.
@return error code or DB_SUCCESS */
UNIV_INTERN
dberr_t
dict_create_remove_zip_dict_references_for_table(
ulint table_id, /*!< in: table id */
trx_t* trx) /*!< in/out: transaction */
{
pars_info_t* info = pars_info_create();
pars_info_add_int4_literal(info, "table_id", table_id);
dberr_t error = que_eval_sql(info,
"PROCEDURE P () IS\n"
"BEGIN\n"
" DELETE FROM SYS_ZIP_DICT_COLS\n"
" WHERE TABLE_ID = :table_id;\n"
"END;\n",
FALSE, trx);
return error;
}

View File

@@ -2,7 +2,7 @@
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
Copyright (c) 2013, 2015, MariaDB Corporation.
Copyright (c) 2013, 2017, 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
@@ -7341,161 +7341,3 @@ dict_tf_to_row_format_string(
return(0);
}
#endif /* !UNIV_HOTBACKUP */
/** Insert a records into SYS_ZIP_DICT.
@retval DB_SUCCESS if OK
@retval dberr_t if the insert failed */
UNIV_INTERN
dberr_t
dict_create_zip_dict(
const char* name, /*!< in: zip_dict name */
ulint name_len, /*!< in: zip_dict name length*/
const char* data, /*!< in: zip_dict data */
ulint data_len) /*!< in: zip_dict data length */
{
dberr_t err = DB_SUCCESS;
trx_t* trx;
ut_ad(name);
ut_ad(data);
rw_lock_x_lock(&dict_operation_lock);
dict_mutex_enter_for_mysql();
trx = trx_allocate_for_background();
trx->op_info = "insert zip_dict";
trx->dict_operation_lock_mode = RW_X_LATCH;
trx_start_if_not_started(trx);
err = dict_create_add_zip_dict(name, name_len, data, data_len, trx);
if (err == DB_SUCCESS) {
trx_commit_for_mysql(trx);
}
else {
trx->op_info = "rollback of internal trx on zip_dict table";
trx_rollback_to_savepoint(trx, NULL);
ut_a(trx->error_state == DB_SUCCESS);
}
trx->op_info = "";
trx->dict_operation_lock_mode = 0;
trx_free_for_background(trx);
dict_mutex_exit_for_mysql();
rw_lock_x_unlock(&dict_operation_lock);
return err;
}
/** Get single compression dictionary id for the given
(table id, column pos) pair.
@retval DB_SUCCESS if OK
@retval DB_RECORD_NOT_FOUND if not found */
UNIV_INTERN
dberr_t
dict_get_dictionary_id_by_key(
ulint table_id, /*!< in: table id */
ulint column_pos, /*!< in: column position */
ulint* dict_id) /*!< out: zip_dict id */
{
dberr_t err = DB_SUCCESS;
trx_t* trx;
rw_lock_s_lock(&dict_operation_lock);
dict_mutex_enter_for_mysql();
trx = trx_allocate_for_background();
trx->op_info = "get zip dict id by composite key";
trx->dict_operation_lock_mode = RW_S_LATCH;
trx_start_if_not_started(trx);
err = dict_create_get_zip_dict_id_by_reference(table_id, column_pos,
dict_id, trx);
trx_commit_for_mysql(trx);
trx->dict_operation_lock_mode = 0;
trx_free_for_background(trx);
dict_mutex_exit_for_mysql();
rw_lock_s_unlock(&dict_operation_lock);
return err;
}
/** Get compression dictionary info (name and data) for the given id.
Allocates memory in name->str and data->str on success.
Must be freed with mem_free().
@retval DB_SUCCESS if OK
@retval DB_RECORD_NOT_FOUND if not found */
UNIV_INTERN
dberr_t
dict_get_dictionary_info_by_id(
ulint dict_id, /*!< in: table name */
char** name, /*!< out: dictionary name */
ulint* name_len, /*!< out: dictionary name length*/
char** data, /*!< out: dictionary data */
ulint* data_len) /*!< out: dictionary data length*/
{
dberr_t err = DB_SUCCESS;
trx_t* trx;
rw_lock_s_lock(&dict_operation_lock);
dict_mutex_enter_for_mysql();
trx = trx_allocate_for_background();
trx->op_info = "get zip dict name and data by id";
trx->dict_operation_lock_mode = RW_S_LATCH;
trx_start_if_not_started(trx);
err = dict_create_get_zip_dict_info_by_id(dict_id, name, name_len,
data, data_len, trx);
trx_commit_for_mysql(trx);
trx->dict_operation_lock_mode = 0;
trx_free_for_background(trx);
dict_mutex_exit_for_mysql();
rw_lock_s_unlock(&dict_operation_lock);
return err;
}
/** Delete a record in SYS_ZIP_DICT with the given name.
@retval DB_SUCCESS if OK
@retval DB_RECORD_NOT_FOUND if not found
@retval DB_ROW_IS_REFERENCED if in use */
UNIV_INTERN
dberr_t
dict_drop_zip_dict(
const char* name, /*!< in: zip_dict name */
ulint name_len) /*!< in: zip_dict name length*/
{
dberr_t err = DB_SUCCESS;
trx_t* trx;
ut_ad(name);
rw_lock_x_lock(&dict_operation_lock);
dict_mutex_enter_for_mysql();
trx = trx_allocate_for_background();
trx->op_info = "delete zip_dict";
trx->dict_operation_lock_mode = RW_X_LATCH;
trx_start_if_not_started(trx);
err = dict_create_remove_zip_dict(name, name_len, trx);
if (err == DB_SUCCESS) {
trx_commit_for_mysql(trx);
}
else {
trx->op_info = "rollback of internal trx on zip_dict table";
trx_rollback_to_savepoint(trx, NULL);
ut_a(trx->error_state == DB_SUCCESS);
}
trx->op_info = "";
trx->dict_operation_lock_mode = 0;
trx_free_for_background(trx);
dict_mutex_exit_for_mysql();
rw_lock_x_unlock(&dict_operation_lock);
return err;
}

View File

@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2016, MariaDB Corporation.
Copyright (c) 2016, 2017, 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
@@ -57,9 +57,7 @@ static const char* SYSTEM_TABLE_NAME[] = {
"SYS_FOREIGN",
"SYS_FOREIGN_COLS",
"SYS_TABLESPACES",
"SYS_DATAFILES",
"SYS_ZIP_DICT",
"SYS_ZIP_DICT_COLS"
"SYS_DATAFILES"
};
/* If this flag is TRUE, then we will load the cluster index's (and tables')
@@ -731,161 +729,6 @@ err_len:
return(NULL);
}
/** This function parses a SYS_ZIP_DICT record, extracts necessary
information from the record and returns to caller.
@return error message, or NULL on success */
UNIV_INTERN
const char*
dict_process_sys_zip_dict(
mem_heap_t* heap, /*!< in/out: heap memory */
ulint zip_size, /*!< in: nonzero=compressed BLOB page size */
const rec_t* rec, /*!< in: current SYS_ZIP_DICT rec */
ulint* id, /*!< out: dict id */
const char** name, /*!< out: dict name */
const char** data, /*!< out: dict data */
ulint* data_len) /*!< out: dict data length */
{
ulint len;
const byte* field;
/* Initialize the output values */
*id = ULINT_UNDEFINED;
*name = NULL;
*data = NULL;
*data_len = 0;
if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
return("delete-marked record in SYS_ZIP_DICT");
}
if (UNIV_UNLIKELY(
rec_get_n_fields_old(rec)!= DICT_NUM_FIELDS__SYS_ZIP_DICT)) {
return("wrong number of columns in SYS_ZIP_DICT record");
}
field = rec_get_nth_field_old(
rec, DICT_FLD__SYS_ZIP_DICT__ID, &len);
if (UNIV_UNLIKELY(len != DICT_FLD_LEN_SPACE)) {
goto err_len;
}
*id = mach_read_from_4(field);
rec_get_nth_field_offs_old(
rec, DICT_FLD__SYS_ZIP_DICT__DB_TRX_ID, &len);
if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
goto err_len;
}
rec_get_nth_field_offs_old(
rec, DICT_FLD__SYS_ZIP_DICT__DB_ROLL_PTR, &len);
if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
goto err_len;
}
field = rec_get_nth_field_old(
rec, DICT_FLD__SYS_ZIP_DICT__NAME, &len);
if (UNIV_UNLIKELY(len == 0 || len == UNIV_SQL_NULL)) {
goto err_len;
}
*name = mem_heap_strdupl(heap, (char*) field, len);
field = rec_get_nth_field_old(
rec, DICT_FLD__SYS_ZIP_DICT__DATA, &len);
if (UNIV_UNLIKELY(len == UNIV_SQL_NULL)) {
goto err_len;
}
if (rec_get_1byte_offs_flag(rec) == 0 &&
rec_2_is_field_extern(rec, DICT_FLD__SYS_ZIP_DICT__DATA)) {
ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
if (UNIV_UNLIKELY
(!memcmp(field + len - BTR_EXTERN_FIELD_REF_SIZE,
field_ref_zero,
BTR_EXTERN_FIELD_REF_SIZE))) {
goto err_len;
}
*data = reinterpret_cast<char*>(
btr_copy_externally_stored_field(data_len, field,
zip_size, len, heap, 0));
}
else {
*data_len = len;
*data = static_cast<char*>(mem_heap_dup(heap, field, len));
}
return(NULL);
err_len:
return("incorrect column length in SYS_ZIP_DICT");
}
/** This function parses a SYS_ZIP_DICT_COLS record, extracts necessary
information from the record and returns to caller.
@return error message, or NULL on success */
UNIV_INTERN
const char*
dict_process_sys_zip_dict_cols(
mem_heap_t* heap, /*!< in/out: heap memory */
const rec_t* rec, /*!< in: current SYS_ZIP_DICT rec */
ulint* table_id, /*!< out: table id */
ulint* column_pos, /*!< out: column position */
ulint* dict_id) /*!< out: dict id */
{
ulint len;
const byte* field;
/* Initialize the output values */
*table_id = ULINT_UNDEFINED;
*column_pos = ULINT_UNDEFINED;
*dict_id = ULINT_UNDEFINED;
if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
return("delete-marked record in SYS_ZIP_DICT_COLS");
}
if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) !=
DICT_NUM_FIELDS__SYS_ZIP_DICT_COLS)) {
return("wrong number of columns in SYS_ZIP_DICT_COLS"
" record");
}
field = rec_get_nth_field_old(
rec, DICT_FLD__SYS_ZIP_DICT_COLS__TABLE_ID, &len);
if (UNIV_UNLIKELY(len != DICT_FLD_LEN_SPACE)) {
err_len:
return("incorrect column length in SYS_ZIP_DICT_COLS");
}
*table_id = mach_read_from_4(field);
field = rec_get_nth_field_old(
rec, DICT_FLD__SYS_ZIP_DICT_COLS__COLUMN_POS, &len);
if (UNIV_UNLIKELY(len != DICT_FLD_LEN_SPACE)) {
goto err_len;
}
*column_pos = mach_read_from_4(field);
rec_get_nth_field_offs_old(
rec, DICT_FLD__SYS_ZIP_DICT_COLS__DB_TRX_ID, &len);
if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
goto err_len;
}
rec_get_nth_field_offs_old(
rec, DICT_FLD__SYS_ZIP_DICT_COLS__DB_ROLL_PTR, &len);
if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
goto err_len;
}
field = rec_get_nth_field_old(
rec, DICT_FLD__SYS_ZIP_DICT_COLS__DICT_ID, &len);
if (UNIV_UNLIKELY(len != DICT_FLD_LEN_SPACE)) {
goto err_len;
}
*dict_id = mach_read_from_4(field);
return(NULL);
}
/********************************************************************//**
Determine the flags of a table as stored in SYS_TABLES.TYPE and N_COLS.
@return ULINT_UNDEFINED if error, else a valid dict_table_t::flags. */

View File

@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
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
@@ -526,15 +527,10 @@ statistics.
@return this function does not return, it calls os_thread_exit() */
extern "C" UNIV_INTERN
os_thread_ret_t
DECLARE_THREAD(dict_stats_thread)(
/*==============================*/
void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter
required by os_thread_create */
DECLARE_THREAD(dict_stats_thread)(void*)
{
ut_a(!srv_read_only_mode);
srv_dict_stats_thread_active = TRUE;
while (!SHUTTING_DOWN()) {
/* Wake up periodically even if not signaled. This is
@@ -557,7 +553,7 @@ DECLARE_THREAD(dict_stats_thread)(
os_event_reset(dict_stats_event);
}
srv_dict_stats_thread_active = FALSE;
srv_dict_stats_thread_active = false;
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit instead of return(). */

View File

@@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (C) 2013, 2015, Google Inc. All Rights Reserved.
Copyright (C) 2014, 2016, MariaDB Corporation. All Rights Reserved.
Copyright (c) 2014, 2017, MariaDB Corporation. All Rights Reserved.
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
@@ -56,7 +56,7 @@ UNIV_INTERN ulong srv_encrypt_tables = 0;
UNIV_INTERN uint srv_n_fil_crypt_threads = 0;
/** No of key rotation threads started */
static uint srv_n_fil_crypt_threads_started = 0;
UNIV_INTERN uint srv_n_fil_crypt_threads_started = 0;
/** At this age or older a space/page will be rotated */
UNIV_INTERN uint srv_fil_crypt_rotate_key_age = 1;
@@ -65,7 +65,7 @@ UNIV_INTERN uint srv_fil_crypt_rotate_key_age = 1;
static os_event_t fil_crypt_event;
/** Event to signal TO the key rotation threads. */
static os_event_t fil_crypt_threads_event;
UNIV_INTERN os_event_t fil_crypt_threads_event;
/** Event for waking up threads throttle */
static os_event_t fil_crypt_throttle_sleep_event;
@@ -1303,10 +1303,20 @@ struct rotate_thread_t {
btr_scrub_t scrub_data; /* thread local data used by btr_scrub-functions
* when iterating pages of tablespace */
/* check if this thread should shutdown */
/** @return whether this thread should terminate */
bool should_shutdown() const {
return ! (srv_shutdown_state == SRV_SHUTDOWN_NONE &&
thread_no < srv_n_fil_crypt_threads);
switch (srv_shutdown_state) {
case SRV_SHUTDOWN_NONE:
case SRV_SHUTDOWN_CLEANUP:
return thread_no >= srv_n_fil_crypt_threads;
case SRV_SHUTDOWN_FLUSH_PHASE:
return true;
case SRV_SHUTDOWN_LAST_PHASE:
case SRV_SHUTDOWN_EXIT_THREADS:
break;
}
ut_ad(0);
return true;
}
};
@@ -2458,18 +2468,6 @@ fil_crypt_threads_init()
}
}
/*********************************************************************
End threads for key rotation */
UNIV_INTERN
void
fil_crypt_threads_end()
/*===================*/
{
if (fil_crypt_threads_inited) {
fil_crypt_set_thread_cnt(0);
}
}
/*********************************************************************
Clean up key rotation threads resources */
UNIV_INTERN
@@ -2480,6 +2478,7 @@ fil_crypt_threads_cleanup()
if (!fil_crypt_threads_inited) {
return;
}
ut_a(!srv_n_fil_crypt_threads_started);
os_event_free(fil_crypt_event);
os_event_free(fil_crypt_threads_event);
mutex_free(&fil_crypt_threads_mutex);

View File

@@ -338,104 +338,6 @@ flst_remove(
mlog_write_ulint(base + FLST_LEN, len - 1, MLOG_4BYTES, mtr);
}
/********************************************************************//**
Cuts off the tail of the list, including the node given. The number of
nodes which will be removed must be provided by the caller, as this function
does not measure the length of the tail. */
UNIV_INTERN
void
flst_cut_end(
/*=========*/
flst_base_node_t* base, /*!< in: pointer to base node of list */
flst_node_t* node2, /*!< in: first node to remove */
ulint n_nodes,/*!< in: number of nodes to remove,
must be >= 1 */
mtr_t* mtr) /*!< in: mini-transaction handle */
{
ulint space;
flst_node_t* node1;
fil_addr_t node1_addr;
fil_addr_t node2_addr;
ulint len;
ut_ad(mtr && node2 && base);
ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
ut_ad(mtr_memo_contains_page(mtr, node2, MTR_MEMO_PAGE_X_FIX));
ut_ad(n_nodes > 0);
buf_ptr_get_fsp_addr(node2, &space, &node2_addr);
node1_addr = flst_get_prev_addr(node2, mtr);
if (!fil_addr_is_null(node1_addr)) {
/* Update next field of node1 */
if (node1_addr.page == node2_addr.page) {
node1 = page_align(node2) + node1_addr.boffset;
} else {
node1 = fut_get_ptr(space,
fil_space_get_zip_size(space),
node1_addr, RW_X_LATCH, mtr);
}
flst_write_addr(node1 + FLST_NEXT, fil_addr_null, mtr);
} else {
/* node2 was first in list: update the field in base */
flst_write_addr(base + FLST_FIRST, fil_addr_null, mtr);
}
flst_write_addr(base + FLST_LAST, node1_addr, mtr);
/* Update len of base node */
len = flst_get_len(base, mtr);
ut_ad(len >= n_nodes);
mlog_write_ulint(base + FLST_LEN, len - n_nodes, MLOG_4BYTES, mtr);
}
/********************************************************************//**
Cuts off the tail of the list, not including the given node. The number of
nodes which will be removed must be provided by the caller, as this function
does not measure the length of the tail. */
UNIV_INTERN
void
flst_truncate_end(
/*==============*/
flst_base_node_t* base, /*!< in: pointer to base node of list */
flst_node_t* node2, /*!< in: first node not to remove */
ulint n_nodes,/*!< in: number of nodes to remove */
mtr_t* mtr) /*!< in: mini-transaction handle */
{
fil_addr_t node2_addr;
ulint len;
ulint space;
ut_ad(mtr && node2 && base);
ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
ut_ad(mtr_memo_contains_page(mtr, node2, MTR_MEMO_PAGE_X_FIX));
if (n_nodes == 0) {
ut_ad(fil_addr_is_null(flst_get_next_addr(node2, mtr)));
return;
}
buf_ptr_get_fsp_addr(node2, &space, &node2_addr);
/* Update next field of node2 */
flst_write_addr(node2 + FLST_NEXT, fil_addr_null, mtr);
flst_write_addr(base + FLST_LAST, node2_addr, mtr);
/* Update len of base node */
len = flst_get_len(base, mtr);
ut_ad(len >= n_nodes);
mlog_write_ulint(base + FLST_LEN, len - n_nodes, MLOG_4BYTES, mtr);
}
/********************************************************************//**
Validates a file-based list.
@return TRUE if ok */

View File

@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2000, 2016, Oracle and/or its affiliates.
Copyright (c) 2013, 2016, MariaDB Corporation.
Copyright (c) 2013, 2017, MariaDB Corporation.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2012, Facebook Inc.
@@ -68,7 +68,6 @@ this program; if not, write to the Free Software Foundation, Inc.,
#include "srv0srv.h"
#include "trx0roll.h"
#include "trx0trx.h"
#include "trx0sys.h"
#include "rem0types.h"
#include "row0ins.h"
@@ -113,14 +112,6 @@ this program; if not, write to the Free Software Foundation, Inc.,
#define thd_get_trx_isolation(X) ((enum_tx_isolation)thd_tx_isolation(X))
#ifndef HAVE_PERCONA_COMPRESSED_COLUMNS
#define COLUMN_FORMAT_TYPE_COMPRESSED 0xBADF00D
#define SQLCOM_CREATE_COMPRESSION_DICTIONARY 0xDECAF
#define SQLCOM_DROP_COMPRESSION_DICTIONARY 0xC0FFEE
#define ER_COMPRESSION_DICTIONARY_DOES_NOT_EXIST 0xDEADFACE
const static LEX_CSTRING null_lex_cstr={0,0};
#endif
#ifdef MYSQL_DYNAMIC_PLUGIN
#define tc_size 400
#define tdc_size 400
@@ -260,7 +251,6 @@ static char* internal_innobase_data_file_path = NULL;
static char* innodb_version_str = (char*) INNODB_VERSION_STR;
extern uint srv_n_fil_crypt_threads;
extern uint srv_fil_crypt_rotate_key_age;
extern uint srv_n_fil_crypt_iops;
@@ -1703,30 +1693,6 @@ normalize_table_name_low(
ibool set_lower_case); /* in: TRUE if we want to set
name to lower case */
#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS
/** Creates a new compression dictionary. */
static
handler_create_zip_dict_result
innobase_create_zip_dict(
handlerton* hton, /*!< in: innobase handlerton */
THD* thd, /*!< in: handle to the MySQL thread */
const char* name, /*!< in: zip dictionary name */
ulint* name_len,
/*!< in/out: zip dictionary name length */
const char* data, /*!< in: zip dictionary data */
ulint* data_len);
/*!< in/out: zip dictionary data length */
/** Drops a existing compression dictionary. */
static
handler_drop_zip_dict_result
innobase_drop_zip_dict(
handlerton* hton, /*!< in: innobase handlerton */
THD* thd, /*!< in: handle to the MySQL thread */
const char* name, /*!< in: zip dictionary name */
ulint* name_len);
/*!< in/out: zip dictionary name length */
#endif
/*************************************************************//**
Checks if buffer pool is big enough to enable backoff algorithm.
InnoDB empty free list algorithm backoff requires free pages
@@ -3854,10 +3820,6 @@ innobase_init(
innodb_remember_check_sysvar_funcs();
#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS
innobase_hton->create_zip_dict = innobase_create_zip_dict;
innobase_hton->drop_zip_dict = innobase_drop_zip_dict;
#endif
ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR);
#ifndef DBUG_OFF
@@ -4631,90 +4593,6 @@ innobase_purge_changed_page_bitmaps(
return (my_bool)log_online_purge_changed_page_bitmaps(lsn);
}
#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS
/** Creates a new compression dictionary. */
static
handler_create_zip_dict_result
innobase_create_zip_dict(
handlerton* hton, /*!< in: innobase handlerton */
THD* thd, /*!< in: handle to the MySQL thread */
const char* name, /*!< in: zip dictionary name */
ulint* name_len,
/*!< in/out: zip dictionary name length */
const char* data, /*!< in: zip dictionary data */
ulint* data_len)
/*!< in/out: zip dictionary data length */
{
handler_create_zip_dict_result result =
HA_CREATE_ZIP_DICT_UNKNOWN_ERROR;
DBUG_ENTER("innobase_create_zip_dict");
DBUG_ASSERT(hton == innodb_hton_ptr);
if (UNIV_UNLIKELY(high_level_read_only)) {
DBUG_RETURN(HA_CREATE_ZIP_DICT_READ_ONLY);
}
if (UNIV_UNLIKELY(*name_len > ZIP_DICT_MAX_NAME_LENGTH)) {
*name_len = ZIP_DICT_MAX_NAME_LENGTH;
DBUG_RETURN(HA_CREATE_ZIP_DICT_NAME_TOO_LONG);
}
if (UNIV_UNLIKELY(*data_len > ZIP_DICT_MAX_DATA_LENGTH)) {
*data_len = ZIP_DICT_MAX_DATA_LENGTH;
DBUG_RETURN(HA_CREATE_ZIP_DICT_DATA_TOO_LONG);
}
switch (dict_create_zip_dict(name, *name_len, data, *data_len)) {
case DB_SUCCESS:
result = HA_CREATE_ZIP_DICT_OK;
break;
case DB_DUPLICATE_KEY:
result = HA_CREATE_ZIP_DICT_ALREADY_EXISTS;
break;
default:
ut_ad(0);
result = HA_CREATE_ZIP_DICT_UNKNOWN_ERROR;
}
DBUG_RETURN(result);
}
/** Drops a existing compression dictionary. */
static
handler_drop_zip_dict_result
innobase_drop_zip_dict(
handlerton* hton, /*!< in: innobase handlerton */
THD* thd, /*!< in: handle to the MySQL thread */
const char* name, /*!< in: zip dictionary name */
ulint* name_len)
/*!< in/out: zip dictionary name length */
{
handler_drop_zip_dict_result result = HA_DROP_ZIP_DICT_UNKNOWN_ERROR;
DBUG_ENTER("innobase_drop_zip_dict");
DBUG_ASSERT(hton == innodb_hton_ptr);
if (UNIV_UNLIKELY(high_level_read_only)) {
DBUG_RETURN(HA_DROP_ZIP_DICT_READ_ONLY);
}
switch (dict_drop_zip_dict(name, *name_len)) {
case DB_SUCCESS:
result = HA_DROP_ZIP_DICT_OK;
break;
case DB_RECORD_NOT_FOUND:
result = HA_DROP_ZIP_DICT_DOES_NOT_EXIST;
break;
case DB_ROW_IS_REFERENCED:
result = HA_DROP_ZIP_DICT_IS_REFERENCED;
break;
default:
ut_ad(0);
result = HA_DROP_ZIP_DICT_UNKNOWN_ERROR;
}
DBUG_RETURN(result);
}
#endif
/*****************************************************************//**
Check whether this is a fake change transaction.
@return TRUE if a fake change transaction */
@@ -4742,7 +4620,7 @@ innobase_commit_low(
#ifdef WITH_WSREP
THD* thd = (THD*)trx->mysql_thd;
const char* tmp = 0;
if (wsrep_on(thd)) {
if (thd && wsrep_on(thd)) {
#ifdef WSREP_PROC_INFO
char info[64];
info[sizeof(info) - 1] = '\0';
@@ -6252,88 +6130,6 @@ func_exit:
DBUG_RETURN(ret);
}
/** This function checks if all the compression dictionaries referenced
in table->fields exist in SYS_ZIP_DICT InnoDB system table.
@return true if all referenced dictionaries exist */
UNIV_INTERN
bool
innobase_check_zip_dicts(
const TABLE* table, /*!< in: table in MySQL data
dictionary */
ulint* dict_ids, /*!< out: identified zip dict ids
(at least n_fields long) */
trx_t* trx, /*!< in: transaction */
const char** err_dict_name) /*!< out: the name of the
zip_dict which does not exist. */
{
DBUG_ENTER("innobase_check_zip_dicts");
bool res = true;
#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS
dberr_t err = DB_SUCCESS;
const size_t n_fields = table->s->fields;
Field* field_ptr;
for (size_t field_idx = 0; err == DB_SUCCESS && field_idx < n_fields;
++field_idx)
{
field_ptr = table->field[field_idx];
if (field_ptr->has_associated_compression_dictionary()) {
err = dict_create_get_zip_dict_id_by_name(
field_ptr->zip_dict_name.str,
field_ptr->zip_dict_name.length,
&dict_ids[field_idx],
trx);
ut_a(err == DB_SUCCESS || err == DB_RECORD_NOT_FOUND);
}
else {
dict_ids[field_idx] = ULINT_UNDEFINED;
}
}
if (err != DB_SUCCESS) {
res = false;
*err_dict_name = field_ptr->zip_dict_name.str;
}
#endif
DBUG_RETURN(res);
}
/** This function creates compression dictionary references in
SYS_ZIP_DICT_COLS InnoDB system table for table_id based on info
in table->fields and provided zip dict ids. */
UNIV_INTERN
void
innobase_create_zip_dict_references(
const TABLE* table, /*!< in: table in MySQL data
dictionary */
table_id_t ib_table_id, /*!< in: table ID in Innodb data
dictionary */
ulint* zip_dict_ids, /*!< in: zip dict ids
(at least n_fields long) */
trx_t* trx) /*!< in: transaction */
{
DBUG_ENTER("innobase_create_zip_dict_references");
dberr_t err = DB_SUCCESS;
const size_t n_fields = table->s->fields;
for (size_t field_idx = 0; err == DB_SUCCESS && field_idx < n_fields;
++field_idx)
{
if (zip_dict_ids[field_idx] != ULINT_UNDEFINED) {
err = dict_create_add_zip_dict_reference(ib_table_id,
table->field[field_idx]->field_index,
zip_dict_ids[field_idx], trx);
ut_a(err == DB_SUCCESS);
}
}
DBUG_VOID_RETURN;
}
/*******************************************************************//**
This function uses index translation table to quickly locate the
requested index structure.
@@ -7762,16 +7558,7 @@ wsrep_store_key_val_for_row(
blob_data = row_mysql_read_blob_ref(&blob_len,
(byte*) (record
+ (ulint) get_field_offset(table, field)),
(ulint) field->pack_length(),
#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS
field->column_format() ==
COLUMN_FORMAT_TYPE_COMPRESSED,
reinterpret_cast<const byte*>(
field->zip_dict_data.str),
field->zip_dict_data.length, prebuilt);
#else
0, 0, 0, prebuilt);
#endif
(ulint) field->pack_length());
true_len = blob_len;
@@ -8066,16 +7853,7 @@ ha_innobase::store_key_val_for_row(
blob_data = row_mysql_read_blob_ref(&blob_len,
(byte*) (record
+ (ulint) get_field_offset(table, field)),
(ulint) field->pack_length(),
#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS
field->column_format() ==
COLUMN_FORMAT_TYPE_COMPRESSED,
reinterpret_cast<const byte*>(
field->zip_dict_data.str),
field->zip_dict_data.length, prebuilt);
#else
0, 0, 0, prebuilt);
#endif
(ulint) field->pack_length());
true_len = blob_len;
@@ -8399,14 +8177,6 @@ build_template_field(
templ->mbminlen = dict_col_get_mbminlen(col);
templ->mbmaxlen = dict_col_get_mbmaxlen(col);
templ->is_unsigned = col->prtype & DATA_UNSIGNED;
#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS
templ->compressed = (field->column_format()
== COLUMN_FORMAT_TYPE_COMPRESSED);
templ->zip_dict_data = field->zip_dict_data;
#else
templ->compressed = 0;
templ->zip_dict_data = null_lex_cstr;
#endif
if (!dict_index_is_clust(index)
&& templ->rec_field_no == ULINT_UNDEFINED) {
@@ -9317,10 +9087,8 @@ calc_row_difference(
case DATA_BLOB:
/* Do not compress blob column while comparing*/
o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len,
false, 0, 0, prebuilt);
n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len,
false, 0, 0, prebuilt);
o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len);
n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len);
break;
@@ -9390,17 +9158,7 @@ calc_row_difference(
TRUE,
new_mysql_row_col,
col_pack_len,
dict_table_is_comp(prebuilt->table),
#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS
field->column_format() ==
COLUMN_FORMAT_TYPE_COMPRESSED,
reinterpret_cast<const byte*>(
field->zip_dict_data.str),
field->zip_dict_data.length,
#else
0, 0, 0,
#endif
prebuilt);
dict_table_is_comp(prebuilt->table));
dfield_copy(&ufield->new_val, &dfield);
} else {
dfield_set_null(&ufield->new_val);
@@ -9572,9 +9330,7 @@ wsrep_calc_row_hash(
switch (col_type) {
case DATA_BLOB:
ptr = row_mysql_read_blob_ref(&len, ptr, len,
false, 0, 0, prebuilt);
ptr = row_mysql_read_blob_ref(&len, ptr, len);
break;
case DATA_VARCHAR:
@@ -11613,7 +11369,6 @@ create_table_def(
ulint unsigned_type;
ulint binary_type;
ulint long_true_varchar;
ulint compressed;
ulint charset_no;
ulint i;
ulint doc_id_col = 0;
@@ -11763,13 +11518,6 @@ create_table_def(
}
}
/* Check if the the field has COMPRESSED attribute */
compressed = 0;
if (field->column_format() ==
COLUMN_FORMAT_TYPE_COMPRESSED) {
compressed = DATA_COMPRESSED;
}
/* First check whether the column to be added has a
system reserved name. */
if (dict_col_name_is_reserved(field->field_name)){
@@ -11790,8 +11538,7 @@ err_col:
dtype_form_prtype(
(ulint) field->type()
| nulls_allowed | unsigned_type
| binary_type | long_true_varchar
| compressed,
| binary_type | long_true_varchar,
charset_no),
col_len);
}
@@ -12841,9 +12588,6 @@ ha_innobase::create(
fil_encryption_t encrypt = (fil_encryption_t)options->encryption;
uint key_id = (uint)options->encryption_key_id;
mem_heap_t* heap = 0;
ulint* zip_dict_ids = 0;
DBUG_ENTER("ha_innobase::create");
DBUG_ASSERT(thd != NULL);
@@ -12940,25 +12684,6 @@ ha_innobase::create(
row_mysql_lock_data_dictionary(trx);
heap = mem_heap_create(form->s->fields * sizeof(ulint));
zip_dict_ids = static_cast<ulint*>(
mem_heap_alloc(heap, form->s->fields * sizeof(ulint)));
/* This is currently required for valgrind because MariaDB does
not currently support compressed columns. */
for (size_t field_idx = 0; field_idx < form->s->fields; ++field_idx) {
zip_dict_ids[field_idx] = ULINT_UNDEFINED;
}
const char* err_zip_dict_name = 0;
if (!innobase_check_zip_dicts(form, zip_dict_ids,
trx, &err_zip_dict_name)) {
error = -1;
my_error(ER_COMPRESSION_DICTIONARY_DOES_NOT_EXIST,
MYF(0), err_zip_dict_name);
goto cleanup;
}
error = create_table_def(trx, form, norm_name, temp_path,
remote_path, flags, flags2, encrypt, key_id);
if (error) {
@@ -13066,22 +12791,6 @@ ha_innobase::create(
dict_table_get_all_fts_indexes(innobase_table, fts->indexes);
}
/*
Adding compression dictionary <-> compressed table column links
to the SYS_ZIP_DICT_COLS table.
*/
ut_a(zip_dict_ids != 0);
{
dict_table_t* local_table = dict_table_open_on_name(
norm_name, TRUE, FALSE, DICT_ERR_IGNORE_NONE);
ut_a(local_table);
table_id_t table_id = local_table->id;
dict_table_close(local_table, TRUE, FALSE);
innobase_create_zip_dict_references(form,
table_id, zip_dict_ids, trx);
}
stmt = innobase_get_stmt(thd, &stmt_len);
if (stmt) {
@@ -13198,9 +12907,6 @@ ha_innobase::create(
trx_free_for_mysql(trx);
if (heap != 0)
mem_heap_free(heap);
DBUG_RETURN(0);
cleanup:
@@ -13210,9 +12916,6 @@ cleanup:
trx_free_for_mysql(trx);
if (heap != 0)
mem_heap_free(heap);
DBUG_RETURN(error);
}
@@ -15625,10 +15328,6 @@ ha_innobase::extra(
row_mysql_prebuilt_free_blob_heap(prebuilt);
}
if (prebuilt->compress_heap) {
row_mysql_prebuilt_free_compress_heap(prebuilt);
}
break;
case HA_EXTRA_RESET_STATE:
reset_template();
@@ -15680,10 +15379,6 @@ ha_innobase::reset()
row_mysql_prebuilt_free_blob_heap(prebuilt);
}
if (prebuilt->compress_heap) {
row_mysql_prebuilt_free_compress_heap(prebuilt);
}
reset_template();
ds_mrr.dsmrr_close();
@@ -15890,11 +15585,7 @@ ha_innobase::external_lock(
&& lock_type == F_WRLCK)
|| thd_sql_command(thd) == SQLCOM_CREATE_INDEX
|| thd_sql_command(thd) == SQLCOM_DROP_INDEX
|| thd_sql_command(thd) == SQLCOM_DELETE
|| thd_sql_command(thd) ==
SQLCOM_CREATE_COMPRESSION_DICTIONARY
|| thd_sql_command(thd) ==
SQLCOM_DROP_COMPRESSION_DICTIONARY)) {
|| thd_sql_command(thd) == SQLCOM_DELETE)) {
if (thd_sql_command(thd) == SQLCOM_CREATE_TABLE)
{
@@ -16662,9 +16353,7 @@ ha_innobase::store_lock(
&& lock_type <= TL_WRITE))
|| sql_command == SQLCOM_CREATE_INDEX
|| sql_command == SQLCOM_DROP_INDEX
|| sql_command == SQLCOM_DELETE
|| sql_command == SQLCOM_CREATE_COMPRESSION_DICTIONARY
|| sql_command == SQLCOM_DROP_COMPRESSION_DICTIONARY)) {
|| sql_command == SQLCOM_DELETE)) {
ib_senderrf(trx->mysql_thd,
IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
@@ -17635,84 +17324,6 @@ ha_innobase::check_if_incompatible_data(
return(COMPATIBLE_DATA_YES);
}
/** This function reads zip dict-related info from SYS_ZIP_DICT
and SYS_ZIP_DICT_COLS for all columns marked with
COLUMN_FORMAT_TYPE_COMPRESSED flag and updates
zip_dict_name / zip_dict_data for those which have associated
compression dictionaries.
*/
UNIV_INTERN
void
ha_innobase::update_field_defs_with_zip_dict_info()
{
DBUG_ENTER("update_field_defs_with_zip_dict_info");
ut_ad(!mutex_own(&dict_sys->mutex));
char norm_name[FN_REFLEN];
normalize_table_name(norm_name, table_share->normalized_path.str);
dict_table_t* ib_table = dict_table_open_on_name(
norm_name, FALSE, FALSE, DICT_ERR_IGNORE_NONE);
/* if dict_table_open_on_name() returns NULL, then it means that
TABLE_SHARE is populated for a table being created and we can
skip filling zip dict info here */
if (ib_table == 0)
DBUG_VOID_RETURN;
#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS
table_id_t ib_table_id = ib_table->id;
dict_table_close(ib_table, FALSE, FALSE);
Field* field;
for (uint i = 0; i < table_share->fields; ++i) {
field = table_share->field[i];
if (field->column_format() ==
COLUMN_FORMAT_TYPE_COMPRESSED) {
bool reference_found = false;
ulint dict_id = 0;
switch (dict_get_dictionary_id_by_key(ib_table_id, i,
&dict_id)) {
case DB_SUCCESS:
reference_found = true;
break;
case DB_RECORD_NOT_FOUND:
reference_found = false;
break;
default:
ut_error;
}
if (reference_found) {
char* local_name = 0;
ulint local_name_len = 0;
char* local_data = 0;
ulint local_data_len = 0;
if (dict_get_dictionary_info_by_id(dict_id,
&local_name, &local_name_len,
&local_data, &local_data_len) !=
DB_SUCCESS) {
ut_error;
}
else {
field->zip_dict_name.str =
local_name;
field->zip_dict_name.length =
local_name_len;
field->zip_dict_data.str =
local_data;
field->zip_dict_data.length =
local_data_len;
}
}
else {
field->zip_dict_name = null_lex_cstr;
field->zip_dict_data = null_lex_cstr;
}
}
}
#endif
DBUG_VOID_RETURN;
}
/****************************************************************//**
Update the system variable innodb_io_capacity_max using the "saved"
value. This function is registered as a callback with MySQL. */
@@ -21622,21 +21233,6 @@ static MYSQL_SYSVAR_BOOL(use_stacktrace, srv_use_stacktrace,
"Print stacktrace on long semaphore wait (off by default supported only on linux)",
NULL, NULL, FALSE);
#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS
static MYSQL_SYSVAR_UINT(compressed_columns_zip_level,
srv_compressed_columns_zip_level,
PLUGIN_VAR_RQCMDARG,
"Compression level used for compressed columns. 0 is no compression"
", 1 is fastest and 9 is best compression. Default is 6.",
NULL, NULL, DEFAULT_COMPRESSION_LEVEL, 0, 9, 0);
static MYSQL_SYSVAR_ULONG(compressed_columns_threshold,
srv_compressed_columns_threshold,
PLUGIN_VAR_RQCMDARG,
"Compress column data if its length exceeds this value. Default is 96",
NULL, NULL, 96, 1, ~0UL, 0);
#endif
static MYSQL_SYSVAR_UINT(compression_level, page_zip_level,
PLUGIN_VAR_RQCMDARG,
"Compression level used for zlib compression. 0 is no compression"
@@ -22015,10 +21611,6 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(locking_fake_changes),
MYSQL_SYSVAR(tmpdir),
MYSQL_SYSVAR(use_stacktrace),
#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS
MYSQL_SYSVAR(compressed_columns_zip_level),
MYSQL_SYSVAR(compressed_columns_threshold),
#endif
MYSQL_SYSVAR(force_primary_key),
MYSQL_SYSVAR(fatal_semaphore_wait_threshold),
/* Table page compression feature */
@@ -22068,10 +21660,6 @@ maria_declare_plugin(xtradb)
i_s_xtradb_read_view,
i_s_xtradb_internal_hash_tables,
i_s_xtradb_rseg,
#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS
i_s_xtradb_zip_dict,
i_s_xtradb_zip_dict_cols,
#endif
i_s_innodb_trx,
i_s_innodb_locks,
i_s_innodb_lock_waits,

View File

@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2016, MariaDB Corporation.
Copyright (c) 2013, 2017, 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
@@ -318,14 +318,6 @@ class ha_innobase: public handler
bool check_if_supported_virtual_columns(void) { return TRUE; }
/** This function reads zip dict-related info from SYS_ZIP_DICT
and SYS_ZIP_DICT_COLS for all columns marked with
COLUMN_FORMAT_TYPE_COMPRESSED flag and updates
zip_dict_name / zip_dict_data for those which have associated
compression dictionaries.
*/
virtual void update_field_defs_with_zip_dict_info();
private:
/** Builds a 'template' to the prebuilt struct.
@@ -741,31 +733,3 @@ ib_push_frm_error(
TABLE* table, /*!< in: MySQL table */
ulint n_keys, /*!< in: InnoDB #keys */
bool push_warning); /*!< in: print warning ? */
/** This function checks if all the compression dictionaries referenced
in table->fields exist in SYS_ZIP_DICT InnoDB system table.
@return true if all referenced dictionaries exist */
UNIV_INTERN
bool
innobase_check_zip_dicts(
const TABLE* table, /*!< in: table in MySQL data
dictionary */
ulint* dict_ids, /*!< out: identified zip dict ids
(at least n_fields long) */
trx_t* trx, /*!< in: transaction */
const char** err_dict_name); /*!< out: the name of the
zip_dict which does not exist. */
/** This function creates compression dictionary references in
SYS_ZIP_DICT_COLS InnoDB system table for table_id based on info
in table->fields and provided zip dict ids. */
UNIV_INTERN
void
innobase_create_zip_dict_references(
const TABLE* table, /*!< in: table in MySQL data
dictionary */
table_id_t ib_table_id, /*!< in: table ID in Innodb data
dictionary */
ulint* zip_dict_ids, /*!< in: zip dict ids
(at least n_fields long) */
trx_t* trx); /*!< in: transaction */

View File

@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2016, MariaDB Corporation. All Rights Reserved.
Copyright (c) 2013, 2017, MariaDB Corporation. All Rights Reserved.
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
@@ -22,11 +22,6 @@ this program; if not, write to the Free Software Foundation, Inc.,
Smart ALTER TABLE
*******************************************************/
#ifndef HAVE_PERCONA_COMPRESSED_COLUMNS
#define COLUMN_FORMAT_TYPE_COMPRESSED 0xBADF00D
#define ER_COMPRESSION_DICTIONARY_DOES_NOT_EXIST 0xDEADFACE
#endif
#include <my_global.h>
#include <unireg.h>
#include <mysqld_error.h>
@@ -1213,15 +1208,6 @@ innobase_col_to_mysql(
field->reset();
if (field->type() == MYSQL_TYPE_VARCHAR) {
if (field->column_format() ==
COLUMN_FORMAT_TYPE_COMPRESSED) {
/* Skip compressed varchar column when
reporting an erroneous row
during index creation or table rebuild. */
field->set_null();
break;
}
/* This is a >= 5.0.3 type true VARCHAR. Store the
length of the data to the first byte or the first
two bytes of dest. */
@@ -2522,14 +2508,7 @@ innobase_build_col_map_add(
byte* buf = static_cast<byte*>(mem_heap_alloc(heap, size));
row_mysql_store_col_in_innobase_format(
dfield, buf, TRUE, field->ptr, size, comp,
#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS
field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED,
reinterpret_cast<const byte*>(field->zip_dict_data.str),
field->zip_dict_data.length, prebuilt);
#else
0,0,0, prebuilt);
#endif
dfield, buf, TRUE, field->ptr, size, comp);
}
/** Construct the translation table for reordering, dropping or
@@ -2783,7 +2762,6 @@ prepare_inplace_alter_table_dict(
ulint num_fts_index;
ha_innobase_inplace_ctx*ctx;
uint sql_idx;
ulint* zip_dict_ids = 0;
DBUG_ENTER("prepare_inplace_alter_table_dict");
@@ -2930,26 +2908,6 @@ prepare_inplace_alter_table_dict(
mode = crypt_data->encryption;
}
zip_dict_ids = static_cast<ulint*>(
mem_heap_alloc(ctx->heap,
altered_table->s->fields * sizeof(ulint)));
/* This is currently required for valgrind because MariaDB does
not currently support compressed columns. */
for (size_t field_idx = 0;
field_idx < altered_table->s->fields;
++field_idx) {
zip_dict_ids[field_idx] = ULINT_UNDEFINED;
}
const char* err_zip_dict_name = 0;
if (!innobase_check_zip_dicts(altered_table, zip_dict_ids,
ctx->trx, &err_zip_dict_name)) {
my_error(ER_COMPRESSION_DICTIONARY_DOES_NOT_EXIST,
MYF(0), err_zip_dict_name);
goto new_clustered_failed;
}
if (innobase_check_foreigns(
ha_alter_info, altered_table, old_table,
user_table, ctx->drop_fk, ctx->num_to_drop_fk)) {
@@ -3056,12 +3014,6 @@ prepare_inplace_alter_table_dict(
}
}
if (field->column_format() ==
COLUMN_FORMAT_TYPE_COMPRESSED) {
field_type |= DATA_COMPRESSED;
}
if (dict_col_name_is_reserved(field->field_name)) {
dict_mem_table_free(ctx->new_table);
my_error(ER_WRONG_COLUMN_NAME, MYF(0),
@@ -3319,17 +3271,6 @@ op_ok:
DBUG_ASSERT(error == DB_SUCCESS);
#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS
/*
Adding compression dictionary <-> compressed table column links
to the SYS_ZIP_DICT_COLS table.
*/
if (zip_dict_ids != 0) {
innobase_create_zip_dict_references(altered_table,
ctx->trx->table_id, zip_dict_ids, ctx->trx);
}
#endif
/* Commit the data dictionary transaction in order to release
the table locks on the system tables. This means that if
MySQL crashes while creating a new primary key inside

View File

@@ -2,6 +2,7 @@
Copyright (c) 2007, 2012, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2010-2012, Percona Inc. All Rights Reserved.
Copyright (c) 2017, 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
@@ -37,7 +38,6 @@ this program; if not, write to the Free Software Foundation, Inc.,
#include <btr0sea.h> /* btr_search_sys */
#include <log0recv.h> /* recv_sys */
#include <fil0fil.h>
#include <dict0crea.h> /* for ZIP_DICT_MAX_* constants */
/* for XTRADB_RSEG table */
#include "trx0trx.h" /* for TRX_QUE_STATE_STR_MAX_LEN */
@@ -542,331 +542,3 @@ UNIV_INTERN struct st_mysql_plugin i_s_xtradb_rseg =
STRUCT_FLD(version_info, INNODB_VERSION_STR),
STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE),
};
#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS
/************************************************************************/
enum zip_dict_field_type
{
zip_dict_field_id,
zip_dict_field_name,
zip_dict_field_zip_dict
};
static ST_FIELD_INFO xtradb_sys_zip_dict_fields_info[] =
{
{ STRUCT_FLD(field_name, "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) },
{ STRUCT_FLD(field_name, "name"),
STRUCT_FLD(field_length, ZIP_DICT_MAX_NAME_LENGTH),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE) },
{ STRUCT_FLD(field_name, "zip_dict"),
STRUCT_FLD(field_length, ZIP_DICT_MAX_DATA_LENGTH),
STRUCT_FLD(field_type, MYSQL_TYPE_BLOB),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE) },
END_OF_ST_FIELD_INFO
};
/** Function to fill INFORMATION_SCHEMA.XTRADB_ZIP_DICT with information
collected by scanning SYS_ZIP_DICT table.
@return 0 on success */
static
int
xtradb_i_s_dict_fill_sys_zip_dict(
THD* thd, /*!< in: thread */
ulint id, /*!< in: dict ID */
const char* name, /*!< in: dict name */
const char* data, /*!< in: dict data */
ulint data_len, /*!< in: dict data length */
TABLE* table_to_fill) /*!< in/out: fill this table */
{
DBUG_ENTER("xtradb_i_s_dict_fill_sys_zip_dict");
Field** fields = table_to_fill->field;
OK(field_store_ulint(fields[zip_dict_field_id], id));
OK(field_store_string(fields[zip_dict_field_name], name));
OK(field_store_blob(fields[zip_dict_field_zip_dict], data,
data_len));
OK(schema_table_store_record(thd, table_to_fill));
DBUG_RETURN(0);
}
/** Function to populate INFORMATION_SCHEMA.XTRADB_ZIP_DICT table.
Loop through each record in SYS_ZIP_DICT, and extract the column
information and fill the INFORMATION_SCHEMA.XTRADB_ZIP_DICT table.
@return 0 on success */
static
int
xtradb_i_s_sys_zip_dict_fill_table(
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
Item* ) /*!< in: condition (not used) */
{
btr_pcur_t pcur;
const rec_t* rec;
mem_heap_t* heap;
mtr_t mtr;
DBUG_ENTER("xtradb_i_s_sys_zip_dict_fill_table");
RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
/* deny access to user without SUPER_ACL privilege */
if (check_global_access(thd, SUPER_ACL)) {
DBUG_RETURN(0);
}
heap = mem_heap_create(1000);
mutex_enter(&dict_sys->mutex);
mtr_start(&mtr);
rec = dict_startscan_system(&pcur, &mtr, SYS_ZIP_DICT);
ulint zip_size = dict_table_zip_size(pcur.btr_cur.index->table);
while (rec) {
const char* err_msg;
ulint id;
const char* name;
const char* data;
ulint data_len;
/* Extract necessary information from a SYS_ZIP_DICT row */
err_msg = dict_process_sys_zip_dict(
heap, zip_size, rec, &id, &name, &data, &data_len);
mtr_commit(&mtr);
mutex_exit(&dict_sys->mutex);
if (!err_msg) {
xtradb_i_s_dict_fill_sys_zip_dict(
thd, id, name, data, data_len,
tables->table);
} else {
push_warning_printf(thd,
Sql_condition::WARN_LEVEL_WARN,
ER_CANT_FIND_SYSTEM_REC, "%s", err_msg);
}
mem_heap_empty(heap);
/* Get the next record */
mutex_enter(&dict_sys->mutex);
mtr_start(&mtr);
rec = dict_getnext_system(&pcur, &mtr);
}
mtr_commit(&mtr);
mutex_exit(&dict_sys->mutex);
mem_heap_free(heap);
DBUG_RETURN(0);
}
static int i_s_xtradb_zip_dict_init(void* p)
{
DBUG_ENTER("i_s_xtradb_zip_dict_init");
ST_SCHEMA_TABLE* schema = static_cast<ST_SCHEMA_TABLE*>(p);
schema->fields_info = xtradb_sys_zip_dict_fields_info;
schema->fill_table = xtradb_i_s_sys_zip_dict_fill_table;
DBUG_RETURN(0);
}
UNIV_INTERN struct st_mysql_plugin i_s_xtradb_zip_dict =
{
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
STRUCT_FLD(info, &i_s_info),
STRUCT_FLD(name, "XTRADB_ZIP_DICT"),
STRUCT_FLD(author, PLUGIN_AUTHOR),
STRUCT_FLD(descr, "InnoDB compression dictionaries information"),
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
STRUCT_FLD(init, i_s_xtradb_zip_dict_init),
STRUCT_FLD(deinit, i_s_common_deinit),
STRUCT_FLD(version, INNODB_VERSION_SHORT),
STRUCT_FLD(status_vars, NULL),
STRUCT_FLD(system_vars, NULL),
STRUCT_FLD(__reserved1, NULL),
STRUCT_FLD(flags, 0UL),
};
enum zip_dict_cols_field_type
{
zip_dict_cols_field_table_id,
zip_dict_cols_field_column_pos,
zip_dict_cols_field_dict_id
};
static ST_FIELD_INFO xtradb_sys_zip_dict_cols_fields_info[] =
{
{ STRUCT_FLD(field_name, "table_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) },
{ STRUCT_FLD(field_name, "column_pos"),
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) },
{ STRUCT_FLD(field_name, "dict_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) },
END_OF_ST_FIELD_INFO
};
/** Function to fill INFORMATION_SCHEMA.XTRADB_ZIP_DICT_COLS with information
collected by scanning SYS_ZIP_DICT_COLS table.
@return 0 on success */
static
int
xtradb_i_s_dict_fill_sys_zip_dict_cols(
THD* thd, /*!< in: thread */
ulint table_id, /*!< in: table ID */
ulint column_pos, /*!< in: column position */
ulint dict_id, /*!< in: dict ID */
TABLE* table_to_fill) /*!< in/out: fill this table */
{
DBUG_ENTER("xtradb_i_s_dict_fill_sys_zip_dict_cols");
Field** fields = table_to_fill->field;
OK(field_store_ulint(fields[zip_dict_cols_field_table_id],
table_id));
OK(field_store_ulint(fields[zip_dict_cols_field_column_pos],
column_pos));
OK(field_store_ulint(fields[zip_dict_cols_field_dict_id],
dict_id));
OK(schema_table_store_record(thd, table_to_fill));
DBUG_RETURN(0);
}
/** Function to populate INFORMATION_SCHEMA.XTRADB_ZIP_DICT_COLS table.
Loop through each record in SYS_ZIP_DICT_COLS, and extract the column
information and fill the INFORMATION_SCHEMA.XTRADB_ZIP_DICT_COLS table.
@return 0 on success */
static
int
xtradb_i_s_sys_zip_dict_cols_fill_table(
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
Item* ) /*!< in: condition (not used) */
{
btr_pcur_t pcur;
const rec_t* rec;
mem_heap_t* heap;
mtr_t mtr;
DBUG_ENTER("xtradb_i_s_sys_zip_dict_cols_fill_table");
RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
/* deny access to user without SUPER_ACL privilege */
if (check_global_access(thd, SUPER_ACL)) {
DBUG_RETURN(0);
}
heap = mem_heap_create(1000);
mutex_enter(&dict_sys->mutex);
mtr_start(&mtr);
rec = dict_startscan_system(&pcur, &mtr, SYS_ZIP_DICT_COLS);
while (rec) {
const char* err_msg;
ulint table_id;
ulint column_pos;
ulint dict_id;
/* Extract necessary information from a SYS_ZIP_DICT_COLS
row */
err_msg = dict_process_sys_zip_dict_cols(
heap, rec, &table_id, &column_pos, &dict_id);
mtr_commit(&mtr);
mutex_exit(&dict_sys->mutex);
if (!err_msg) {
xtradb_i_s_dict_fill_sys_zip_dict_cols(
thd, table_id, column_pos, dict_id,
tables->table);
} else {
push_warning_printf(thd,
Sql_condition::WARN_LEVEL_WARN,
ER_CANT_FIND_SYSTEM_REC, "%s", err_msg);
}
mem_heap_empty(heap);
/* Get the next record */
mutex_enter(&dict_sys->mutex);
mtr_start(&mtr);
rec = dict_getnext_system(&pcur, &mtr);
}
mtr_commit(&mtr);
mutex_exit(&dict_sys->mutex);
mem_heap_free(heap);
DBUG_RETURN(0);
}
static int i_s_xtradb_zip_dict_cols_init(void* p)
{
DBUG_ENTER("i_s_xtradb_zip_dict_cols_init");
ST_SCHEMA_TABLE* schema = static_cast<ST_SCHEMA_TABLE*>(p);
schema->fields_info = xtradb_sys_zip_dict_cols_fields_info;
schema->fill_table = xtradb_i_s_sys_zip_dict_cols_fill_table;
DBUG_RETURN(0);
}
UNIV_INTERN struct st_mysql_plugin i_s_xtradb_zip_dict_cols =
{
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
STRUCT_FLD(info, &i_s_info),
STRUCT_FLD(name, "XTRADB_ZIP_DICT_COLS"),
STRUCT_FLD(author, PLUGIN_AUTHOR),
STRUCT_FLD(descr, "InnoDB compressed columns information"),
STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
STRUCT_FLD(init, i_s_xtradb_zip_dict_cols_init),
STRUCT_FLD(deinit, i_s_common_deinit),
STRUCT_FLD(version, INNODB_VERSION_SHORT),
STRUCT_FLD(status_vars, NULL),
STRUCT_FLD(system_vars, NULL),
STRUCT_FLD(__reserved1, NULL),
STRUCT_FLD(flags, 0UL),
};
#endif

View File

@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2010-2012, Percona Inc. All Rights Reserved.
Copyright (c) 2017, 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
@@ -22,7 +23,5 @@ this program; if not, write to the Free Software Foundation, Inc.,
extern struct st_mysql_plugin i_s_xtradb_read_view;
extern struct st_mysql_plugin i_s_xtradb_internal_hash_tables;
extern struct st_mysql_plugin i_s_xtradb_rseg;
extern struct st_mysql_plugin i_s_xtradb_zip_dict;
extern struct st_mysql_plugin i_s_xtradb_zip_dict_cols;
#endif /* XTRADB_I_S_H */

View File

@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 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
@@ -170,9 +171,6 @@ be less than 256 */
type when the column is true VARCHAR where
MySQL uses 2 bytes to store the data len;
for shorter VARCHARs MySQL uses only 1 byte */
#define DATA_COMPRESSED 16384 /* this is ORed to the precise data
type when the column has COLUMN_FORMAT =
COMPRESSED attribute*/
/*-------------------------------------------*/
/* This many bytes we need to store the type information affecting the
@@ -503,17 +501,6 @@ dtype_print(
/*========*/
const dtype_t* type); /*!< in: type */
/**
Calculates the number of extra bytes needed for compression header
depending on precise column type.
@reval 0 if prtype does not include DATA_COMPRESSED flag
@reval ZIP_COLUMN_HEADER_LENGTH if prtype includes DATA_COMPRESSED flag
*/
UNIV_INLINE
ulint
prtype_get_compression_extra(
ulint prtype); /*!< in: precise type */
/* Structure for an SQL data type.
If you add fields to this structure, be sure to initialize them everywhere.
This structure is initialized in the following functions:

View File

@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 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
@@ -710,18 +711,3 @@ dtype_get_sql_null_size(
0, 0));
#endif /* !UNIV_HOTBACKUP */
}
/**
Calculates the number of extra bytes needed for compression header
depending on precise column type.
@reval 0 if prtype does not include DATA_COMPRESSED flag
@reval ZIP_COLUMN_HEADER_LENGTH if prtype includes DATA_COMPRESSED flag
*/
UNIV_INLINE
ulint
prtype_get_compression_extra(
ulint prtype) /*!< in: precise type */
{
return (prtype & DATA_COMPRESSED) != 0 ?
ZIP_COLUMN_HEADER_LENGTH : 0;
}

View File

@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 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
@@ -324,38 +325,6 @@ enum dict_fld_sys_datafiles_enum {
DICT_FLD__SYS_DATAFILES__PATH = 3,
DICT_NUM_FIELDS__SYS_DATAFILES = 4
};
/* The columns in SYS_DICT */
enum dict_col_sys_zip_dict_enum {
DICT_COL__SYS_ZIP_DICT__ID = 0,
DICT_COL__SYS_ZIP_DICT__NAME = 1,
DICT_COL__SYS_ZIP_DICT__DATA = 2,
DICT_NUM_COLS__SYS_ZIP_DICT = 3
};
/* The field numbers in the SYS_DICT clustered index */
enum dict_fld_sys_zip_dict_enum {
DICT_FLD__SYS_ZIP_DICT__ID = 0,
DICT_FLD__SYS_ZIP_DICT__DB_TRX_ID = 1,
DICT_FLD__SYS_ZIP_DICT__DB_ROLL_PTR = 2,
DICT_FLD__SYS_ZIP_DICT__NAME = 3,
DICT_FLD__SYS_ZIP_DICT__DATA = 4,
DICT_NUM_FIELDS__SYS_ZIP_DICT = 5
};
/* The columns in SYS_DICT_COLS */
enum dict_col_sys_zip_dict_cols_enum {
DICT_COL__SYS_ZIP_DICT_COLS__TABLE_ID = 0,
DICT_COL__SYS_ZIP_DICT_COLS__COLUMN_POS = 1,
DICT_COL__SYS_ZIP_DICT_COLS__DICT_ID = 2,
DICT_NUM_COLS__SYS_ZIP_DICT_COLS = 3
};
/* The field numbers in the SYS_DICT_COLS clustered index */
enum dict_fld_sys_zip_dict_cols_enum {
DICT_FLD__SYS_ZIP_DICT_COLS__TABLE_ID = 0,
DICT_FLD__SYS_ZIP_DICT_COLS__COLUMN_POS = 1,
DICT_FLD__SYS_ZIP_DICT_COLS__DB_TRX_ID = 2,
DICT_FLD__SYS_ZIP_DICT_COLS__DB_ROLL_PTR = 3,
DICT_FLD__SYS_ZIP_DICT_COLS__DICT_ID = 4,
DICT_NUM_FIELDS__SYS_ZIP_DICT_COLS = 5
};
/* A number of the columns above occur in multiple tables. These are the
length of thos fields. */

View File

@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 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
@@ -92,5 +93,3 @@ dict_is_sys_table(
{
return(id < DICT_HDR_FIRST_ID);
}

View File

@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 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
@@ -167,18 +168,6 @@ dberr_t
dict_create_or_check_sys_tablespace(void);
/*=====================================*/
#define ZIP_DICT_MAX_NAME_LENGTH 64
/* Max window size (2^15) minus 262 */
#define ZIP_DICT_MAX_DATA_LENGTH 32506
/** Creates the zip_dict system table inside InnoDB
at server bootstrap or server start if it is not found or is
not of the right form.
@return DB_SUCCESS or error code */
UNIV_INTERN
dberr_t
dict_create_or_check_sys_zip_dict(void);
/********************************************************************//**
Add a single tablespace definition to the data dictionary tables in the
database.
@@ -195,83 +184,6 @@ dict_create_add_tablespace_to_dictionary(
bool commit); /*!< in: if true then commit the
transaction */
/** Add a single compression dictionary definition to the SYS_ZIP_DICT
InnoDB system table.
@return error code or DB_SUCCESS */
UNIV_INTERN
dberr_t
dict_create_add_zip_dict(
const char* name, /*!< in: dict name */
ulint name_len, /*!< in: dict name length */
const char* data, /*!< in: dict data */
ulint data_len, /*!< in: dict data length */
trx_t* trx); /*!< in/out: transaction */
/** Add a single compression dictionary reference to the SYS_ZIP_DICT_COLS
InnoDB system table.
@return error code or DB_SUCCESS */
UNIV_INTERN
dberr_t
dict_create_add_zip_dict_reference(
ulint table_id, /*!< in: table id */
ulint column_pos, /*!< in: column position */
ulint dict_id, /*!< in: dict id */
trx_t* trx); /*!< in/out: transaction */
/** Get a single compression dictionary id for the given
(table id, column pos) pair.
@return error code or DB_SUCCESS */
UNIV_INTERN
dberr_t
dict_create_get_zip_dict_id_by_reference(
ulint table_id, /*!< in: table id */
ulint column_pos, /*!< in: column position */
ulint* dict_id, /*!< out: dict id */
trx_t* trx); /*!< in/out: transaction */
/** Get compression dictionary id for the given name.
@return error code or DB_SUCCESS */
UNIV_INTERN
dberr_t
dict_create_get_zip_dict_id_by_name(
const char* dict_name, /*!< in: dict name */
ulint dict_name_len, /*!< in: dict name length */
ulint* dict_id, /*!< out: dict id */
trx_t* trx); /*!< in/out: transaction */
/** Get compression dictionary info (name and data) for the given id.
Allocates memory for name and data on success.
Must be freed with mem_free().
@return error code or DB_SUCCESS */
UNIV_INTERN
dberr_t
dict_create_get_zip_dict_info_by_id(
ulint dict_id, /*!< in: dict id */
char** name, /*!< out: dict name */
ulint* name_len, /*!< out: dict name length */
char** data, /*!< out: dict data */
ulint* data_len, /*!< out: dict data length */
trx_t* trx); /*!< in/out: transaction */
/** Remove a single compression dictionary from the data dictionary
tables in the database.
@return error code or DB_SUCCESS */
UNIV_INTERN
dberr_t
dict_create_remove_zip_dict(
const char* name, /*!< in: dict name */
ulint name_len, /*!< in: dict name length */
trx_t* trx); /*!< in/out: transaction */
/** Remove all compression dictionary references for the given table ID from
the data dictionary tables in the database.
@return error code or DB_SUCCESS */
UNIV_INTERN
dberr_t
dict_create_remove_zip_dict_references_for_table(
ulint table_id, /*!< in: table id */
trx_t* trx); /*!< in/out: transaction */
/********************************************************************//**
Add a foreign key definition to the data dictionary tables.
@return error code or DB_SUCCESS */

View File

@@ -2,7 +2,7 @@
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
Copyright (c) 2013, 2015, MariaDB Corporation.
Copyright (c) 2013, 2017, 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
@@ -1910,52 +1910,6 @@ dict_table_set_corrupt_by_space(
ulint space_id,
ibool need_mutex);
/** Insert a records into SYS_ZIP_DICT.
@retval DB_SUCCESS if OK
@retval dberr_t if the insert failed */
UNIV_INTERN
dberr_t
dict_create_zip_dict(
const char* name, /*!< in: zip_dict name */
ulint name_len, /*!< in: zip_dict name length*/
const char* data, /*!< in: zip_dict data */
ulint data_len); /*!< in: zip_dict data length */
/** Get single compression dictionary id for the given
(table id, column pos) pair.
@retval DB_SUCCESS if OK
@retval DB_RECORD_NOT_FOUND if not found */
UNIV_INTERN
dberr_t
dict_get_dictionary_id_by_key(
ulint table_id, /*!< in: table id */
ulint column_pos, /*!< in: column position */
ulint* dict_id); /*!< out: zip_dict id */
/** Get compression dictionary info (name and data) for the given id.
Allocates memory in name->str and data->str on success.
Must be freed with mem_free().
@retval DB_SUCCESS if OK
@retval DB_RECORD_NOT_FOUND if not found */
UNIV_INTERN
dberr_t
dict_get_dictionary_info_by_id(
ulint dict_id, /*!< in: table name */
char** name, /*!< out: dictionary name */
ulint* name_len, /*!< out: dictionary name length*/
char** data, /*!< out: dictionary data */
ulint* data_len); /*!< out: dictionary data length*/
/** Delete a record in SYS_ZIP_DICT with the given name.
@retval DB_SUCCESS if OK
@retval DB_RECORD_NOT_FOUND if not found
@retval DB_ROW_IS_REFERENCED if in use */
UNIV_INTERN
dberr_t
dict_drop_zip_dict(
const char* name, /*!< in: zip_dict name */
ulint name_len); /*!< in: zip_dict name length*/
#ifndef UNIV_NONINL
#include "dict0dict.ic"
#endif

View File

@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 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
@@ -44,8 +45,6 @@ enum dict_system_id_t {
SYS_FOREIGN_COLS,
SYS_TABLESPACES,
SYS_DATAFILES,
SYS_ZIP_DICT,
SYS_ZIP_DICT_COLS,
/* This must be last item. Defines the number of system tables. */
SYS_NUM_SYSTEM_TABLES
@@ -389,32 +388,6 @@ dict_process_sys_datafiles(
ulint* space, /*!< out: pace id */
const char** path); /*!< out: datafile path */
/** This function parses a SYS_ZIP_DICT record, extracts necessary
information from the record and returns to caller.
@return error message, or NULL on success */
UNIV_INTERN
const char*
dict_process_sys_zip_dict(
mem_heap_t* heap, /*!< in/out: heap memory */
ulint zip_size, /*!< in: nonzero=compressed BLOB page size */
const rec_t* rec, /*!< in: current SYS_ZIP_DICT rec */
ulint* id, /*!< out: dict id */
const char** name, /*!< out: dict name */
const char** data, /*!< out: dict data */
ulint* data_len); /*!< out: dict data length */
/** This function parses a SYS_ZIP_DICT_COLS record, extracts necessary
information from the record and returns to caller.
@return error message, or NULL on success */
UNIV_INTERN
const char*
dict_process_sys_zip_dict_cols(
mem_heap_t* heap, /*!< in/out: heap memory */
const rec_t* rec, /*!< in: current SYS_ZIP_DICT rec */
ulint* table_id, /*!< out: table id */
ulint* column_pos, /*!< out: column position */
ulint* dict_id); /*!< out: dict id */
/********************************************************************//**
Get the filepath for a spaceid from SYS_DATAFILES. This function provides
a temporary heap which is used for the table lookup, but not for the path.

View File

@@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (C) 2013, 2015, Google Inc. All Rights Reserved.
Copyright (c) 2015, 2016, MariaDB Corporation.
Copyright (c) 2015, 2017, 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
@@ -26,6 +26,8 @@ Created 04/01/2015 Jan Lindström
#ifndef fil0crypt_h
#define fil0crypt_h
#include "os0sync.h"
/**
* Magic pattern in start of crypt data on page 0
*/
@@ -45,6 +47,8 @@ typedef enum {
FIL_SPACE_ENCRYPTION_OFF = 2 /* Tablespace is not encrypted */
} fil_encryption_t;
extern os_event_t fil_crypt_threads_event;
/**
* CRYPT_SCHEME_UNENCRYPTED
*
@@ -391,12 +395,6 @@ fil_crypt_set_thread_cnt(
/*=====================*/
uint new_cnt); /*!< in: requested #threads */
/*********************************************************************
End threads for key rotation */
UNIV_INTERN
void
fil_crypt_threads_end();
/*********************************************************************
Cleanup resources for threads for key rotation */
UNIV_INTERN

View File

@@ -102,31 +102,6 @@ flst_remove(
flst_node_t* node2, /*!< in: node to remove */
mtr_t* mtr); /*!< in: mini-transaction handle */
/********************************************************************//**
Cuts off the tail of the list, including the node given. The number of
nodes which will be removed must be provided by the caller, as this function
does not measure the length of the tail. */
UNIV_INTERN
void
flst_cut_end(
/*=========*/
flst_base_node_t* base, /*!< in: pointer to base node of list */
flst_node_t* node2, /*!< in: first node to remove */
ulint n_nodes,/*!< in: number of nodes to remove,
must be >= 1 */
mtr_t* mtr); /*!< in: mini-transaction handle */
/********************************************************************//**
Cuts off the tail of the list, not including the given node. The number of
nodes which will be removed must be provided by the caller, as this function
does not measure the length of the tail. */
UNIV_INTERN
void
flst_truncate_end(
/*==============*/
flst_base_node_t* base, /*!< in: pointer to base node of list */
flst_node_t* node2, /*!< in: first node not to remove */
ulint n_nodes,/*!< in: number of nodes to remove */
mtr_t* mtr); /*!< in: mini-transaction handle */
/********************************************************************//**
Gets list length.
@return length */
UNIV_INLINE

View File

@@ -2,6 +2,7 @@
Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2009, Google Inc.
Copyright (c) 2017, MariaDB Corporation
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -1070,22 +1071,9 @@ struct log_t{
/* @} */
#endif /* UNIV_LOG_ARCHIVE */
extern os_event_t log_scrub_event;
/* log scrubbing speed, in bytes/sec */
extern ulonglong innodb_scrub_log_speed;
/*****************************************************************//**
This is the main thread for log scrub. It waits for an event and
when waked up fills current log block with dummy records and
sleeps again.
@return this function does not return, it calls os_thread_exit() */
extern "C" UNIV_INTERN
os_thread_ret_t
DECLARE_THREAD(log_scrub_thread)(
/*===============================*/
void* arg); /*!< in: a dummy parameter
required by os_thread_create */
#ifndef UNIV_NONINL
#include "log0log.ic"
#endif

View File

@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 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
@@ -42,9 +43,6 @@ struct SysIndexCallback;
extern ibool row_rollback_on_timeout;
extern uint srv_compressed_columns_zip_level;
extern ulong srv_compressed_columns_threshold;
struct row_prebuilt_t;
/*******************************************************************//**
@@ -56,48 +54,6 @@ row_mysql_prebuilt_free_blob_heap(
row_prebuilt_t* prebuilt); /*!< in: prebuilt struct of a
ha_innobase:: table handle */
/** Frees the compress heap in prebuilt when no longer needed. */
UNIV_INTERN
void
row_mysql_prebuilt_free_compress_heap(
row_prebuilt_t* prebuilt); /*!< in: prebuilt struct of a
ha_innobase:: table handle */
/** Uncompress blob/text/varchar column using zlib
@return pointer to the uncompressed data */
const byte*
row_decompress_column(
const byte* data, /*!< in: data in innodb(compressed) format */
ulint *len, /*!< in: data length; out: length of
decompressed data*/
const byte* dict_data,
/*!< in: optional dictionary data used for
decompression */
ulint dict_data_len,
/*!< in: optional dictionary data length */
row_prebuilt_t* prebuilt);
/*!< in: use prebuilt->compress_heap only
here*/
/** Compress blob/text/varchar column using zlib
@return pointer to the compressed data */
byte*
row_compress_column(
const byte* data, /*!< in: data in mysql(uncompressed)
format */
ulint *len, /*!< in: data length; out: length of
compressed data*/
ulint lenlen, /*!< in: bytes used to store the length of
data */
const byte* dict_data,
/*!< in: optional dictionary data used for
compression */
ulint dict_data_len,
/*!< in: optional dictionary data length */
row_prebuilt_t* prebuilt);
/*!< in: use prebuilt->compress_heap only
here*/
/*******************************************************************//**
Stores a >= 5.0.3 format true VARCHAR length to dest, in the MySQL row
format.
@@ -136,21 +92,10 @@ row_mysql_store_blob_ref(
to 4 bytes */
const void* data, /*!< in: BLOB data; if the value to store
is SQL NULL this should be NULL pointer */
ulint len, /*!< in: BLOB length; if the value to store
ulint len); /*!< in: BLOB length; if the value to store
is SQL NULL this should be 0; remember
also to set the NULL bit in the MySQL record
header! */
bool need_decompression,
/*!< in: if the data need to be compressed*/
const byte* dict_data,
/*!< in: optional compression dictionary
data */
ulint dict_data_len,
/*!< in: optional compression dictionary data
length */
row_prebuilt_t* prebuilt);
/*<! in: use prebuilt->compress_heap only
here */
/*******************************************************************//**
Reads a reference to a BLOB in the MySQL format.
@return pointer to BLOB data */
@@ -161,17 +106,8 @@ row_mysql_read_blob_ref(
ulint* len, /*!< out: BLOB length */
const byte* ref, /*!< in: BLOB reference in the
MySQL format */
ulint col_len, /*!< in: BLOB reference length
ulint col_len); /*!< in: BLOB reference length
(not BLOB length) */
bool need_compression,
/*!< in: if the data need to be
compressed*/
const byte* dict_data, /*!< in: optional compression
dictionary data */
ulint dict_data_len, /*!< in: optional compression
dictionary data length */
row_prebuilt_t* prebuilt); /*!< in: use prebuilt->compress_heap
only here */
/**************************************************************//**
Pad a column with spaces. */
UNIV_INTERN
@@ -219,16 +155,7 @@ row_mysql_store_col_in_innobase_format(
necessarily the length of the actual
payload data; if the column is a true
VARCHAR then this is irrelevant */
ulint comp, /*!< in: nonzero=compact format */
bool need_compression,
/*!< in: if the data need to be
compressed */
const byte* dict_data, /*!< in: optional compression
dictionary data */
ulint dict_data_len, /*!< in: optional compression
dictionary data length */
row_prebuilt_t* prebuilt); /*!< in: use prebuilt->compress_heap
only here */
ulint comp); /*!< in: nonzero=compact format */
/****************************************************************//**
Handles user errors and lock waits detected by the database engine.
@return true if it was a lock wait and we should continue running the
@@ -730,8 +657,6 @@ struct mysql_row_templ_t {
ulint is_unsigned; /*!< if a column type is an integer
type and this field is != 0, then
it is an unsigned integer type */
bool compressed; /*!< if column format is compressed */
LEX_CSTRING zip_dict_data; /*!< associated compression dictionary */
};
#define MYSQL_FETCH_CACHE_SIZE 8
@@ -931,8 +856,6 @@ struct row_prebuilt_t {
in fetch_cache */
mem_heap_t* blob_heap; /*!< in SELECTS BLOB fields are copied
to this heap */
mem_heap_t* compress_heap; /*!< memory heap used to compress
/decompress blob column*/
mem_heap_t* old_vers_heap; /*!< memory heap where a previous
version is built in consistent read */
bool in_fts_query; /*!< Whether we are in a FTS query */

View File

@@ -3,7 +3,7 @@
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2008, 2009, Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2016, MariaDB Corporation
Copyright (c) 2013, 2017, MariaDB Corporation
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -346,7 +346,6 @@ extern char** srv_data_file_names;
extern ulint* srv_data_file_sizes;
extern ulint* srv_data_file_is_raw_partition;
/** Whether the redo log tracking is currently enabled. Note that it is
possible for the log tracker thread to be running and the tracking to be
disabled */
@@ -356,6 +355,9 @@ extern ulonglong srv_max_bitmap_file_size;
extern
ulonglong srv_max_changed_pages;
extern uint srv_n_fil_crypt_threads;
extern uint srv_n_fil_crypt_threads_started;
extern ibool srv_auto_extend_last_data_file;
extern ulint srv_last_file_size_max;
extern char* srv_log_group_home_dir;
@@ -574,19 +576,17 @@ extern ibool srv_print_verbose_log;
"tables instead, see " REFMAN "innodb-i_s-tables.html"
extern ibool srv_print_innodb_table_monitor;
extern ibool srv_monitor_active;
extern ibool srv_error_monitor_active;
extern bool srv_monitor_active;
extern bool srv_error_monitor_active;
/* TRUE during the lifetime of the buffer pool dump/load thread */
extern ibool srv_buf_dump_thread_active;
extern bool srv_buf_dump_thread_active;
/* TRUE during the lifetime of the stats thread */
extern ibool srv_dict_stats_thread_active;
extern bool srv_dict_stats_thread_active;
/* TRUE if enable log scrubbing */
extern my_bool srv_scrub_log;
/* TRUE during the lifetime of the log scrub thread */
extern ibool srv_log_scrub_thread_active;
extern ulong srv_n_spin_wait_rounds;
extern ulong srv_n_free_tickets_to_enter;
@@ -1082,15 +1082,6 @@ srv_release_threads(
enum srv_thread_type type, /*!< in: thread type */
ulint n); /*!< in: number of threads to release */
/**********************************************************************//**
Check whether any background thread are active. If so print which thread
is active. Send the threads wakeup signal.
@return name of thread that is active or NULL */
UNIV_INTERN
const char*
srv_any_background_threads_are_active(void);
/*=======================================*/
/**********************************************************************//**
Wakeup the purge threads. */
UNIV_INTERN

View File

@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
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
@@ -510,11 +511,7 @@ A thread which wakes up threads whose lock wait may have lasted too long.
@return a dummy parameter */
extern "C" UNIV_INTERN
os_thread_ret_t
DECLARE_THREAD(lock_wait_timeout_thread)(
/*=====================================*/
void* arg MY_ATTRIBUTE((unused)))
/* in: a dummy parameter required by
os_thread_create */
DECLARE_THREAD(lock_wait_timeout_thread)(void*)
{
ib_int64_t sig_count = 0;
os_event_t event = lock_sys->timeout_event;
@@ -525,8 +522,6 @@ DECLARE_THREAD(lock_wait_timeout_thread)(
pfs_register_thread(srv_lock_timeout_thread_key);
#endif /* UNIV_PFS_THREAD */
lock_sys->timeout_thread_active = true;
do {
srv_slot_t* slot;

View File

@@ -2,7 +2,7 @@
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Google Inc.
Copyright (C) 2014, 2016, MariaDB Corporation. All Rights Reserved.
Copyright (c) 2014, 2017, MariaDB Corporation. All Rights Reserved.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -52,9 +52,11 @@ Created 12/9/1995 Heikki Tuuri
#include "buf0buf.h"
#include "buf0flu.h"
#include "srv0srv.h"
#include "lock0lock.h"
#include "log0recv.h"
#include "fil0fil.h"
#include "dict0boot.h"
#include "dict0stats_bg.h" /* dict_stats_event */
#include "srv0srv.h"
#include "srv0start.h"
#include "trx0sys.h"
@@ -95,6 +97,10 @@ UNIV_INTERN log_t* log_sys = NULL;
UNIV_INTERN log_checksum_func_t log_checksum_algorithm_ptr =
log_block_calc_checksum_innodb;
extern "C" UNIV_INTERN
os_thread_ret_t
DECLARE_THREAD(log_scrub_thread)(void*);
/* Next log block number to do dummy record filling if no log records written
for a while */
static ulint next_lbn_to_pad = 0;
@@ -167,6 +173,11 @@ the previous */
#define LOG_ARCHIVE_READ 1
#define LOG_ARCHIVE_WRITE 2
/** Event to wake up the log scrub thread */
static os_event_t log_scrub_event;
static bool log_scrub_thread_active;
/******************************************************//**
Completes a checkpoint write i/o to a log file. */
static
@@ -1049,6 +1060,12 @@ log_init(void)
mutex_exit(&(log_sys->mutex));
log_scrub_thread_active = !srv_read_only_mode && srv_scrub_log;
if (log_scrub_thread_active) {
log_scrub_event = os_event_create();
os_thread_create(log_scrub_thread, NULL, NULL);
}
#ifdef UNIV_LOG_DEBUG
recv_sys_create();
recv_sys_init(buf_pool_get_curr_size());
@@ -3545,8 +3562,6 @@ logs_empty_and_mark_files_at_shutdown(void)
ulint count = 0;
ulint total_trx;
ulint pending_io;
enum srv_thread_type active_thd;
const char* thread_name;
ibool server_busy;
ib_logf(IB_LOG_LEVEL_INFO, "Starting shutdown...");
@@ -3566,29 +3581,17 @@ logs_empty_and_mark_files_at_shutdown(void)
srv_shutdown_state = SRV_SHUTDOWN_CLEANUP;
loop:
if (!srv_read_only_mode) {
os_event_set(srv_error_event);
os_event_set(srv_monitor_event);
os_event_set(srv_buf_dump_event);
os_event_set(lock_sys->timeout_event);
os_event_set(dict_stats_event);
}
os_thread_sleep(100000);
count++;
/* We need the monitor threads to stop before we proceed with
a shutdown. */
thread_name = srv_any_background_threads_are_active();
if (thread_name != NULL) {
/* Print a message every 60 seconds if we are waiting
for the monitor thread to exit. Master and worker
threads check will be done later. */
if (srv_print_verbose_log && count > 600) {
ib_logf(IB_LOG_LEVEL_INFO,
"Waiting for %s to exit", thread_name);
count = 0;
}
goto loop;
}
/* Check that there are no longer transactions, except for
PREPARED ones. We need this wait even for the 'very fast'
shutdown, because the InnoDB layer may have committed or
@@ -3609,55 +3612,61 @@ loop:
goto loop;
}
/* Check that the background threads are suspended */
/* We need these threads to stop early in shutdown. */
const char* thread_name;
active_thd = srv_get_active_thread_type();
if (srv_error_monitor_active) {
thread_name = "srv_error_monitor_thread";
} else if (srv_monitor_active) {
thread_name = "srv_monitor_thread";
} else if (srv_dict_stats_thread_active) {
thread_name = "dict_stats_thread";
} else if (lock_sys->timeout_thread_active) {
thread_name = "lock_wait_timeout_thread";
} else if (srv_buf_dump_thread_active) {
thread_name = "buf_dump_thread";
} else {
thread_name = NULL;
}
if (active_thd != SRV_NONE) {
if (active_thd == SRV_PURGE) {
srv_purge_wakeup();
}
/* The srv_lock_timeout_thread, srv_error_monitor_thread
and srv_monitor_thread should already exit by now. The
only threads to be suspended are the master threads
and worker threads (purge threads). Print the thread
type if any of such threads not in suspended mode */
if (thread_name) {
ut_ad(!srv_read_only_mode);
wait_suspend_loop:
if (srv_print_verbose_log && count > 600) {
const char* thread_type = "<null>";
switch (active_thd) {
case SRV_NONE:
/* This shouldn't happen because we've
already checked for this case before
entering the if(). We handle it here
to avoid a compiler warning. */
ut_error;
case SRV_WORKER:
thread_type = "worker threads";
break;
case SRV_MASTER:
thread_type = "master thread";
break;
case SRV_PURGE:
thread_type = "purge thread";
break;
}
ib_logf(IB_LOG_LEVEL_INFO,
"Waiting for %s to be suspended",
thread_type);
"Waiting for %s to exit", thread_name);
count = 0;
}
goto loop;
}
/* Check that the background threads are suspended */
switch (srv_get_active_thread_type()) {
case SRV_NONE:
srv_shutdown_state = SRV_SHUTDOWN_FLUSH_PHASE;
if (!srv_n_fil_crypt_threads_started) {
break;
}
os_event_set(fil_crypt_threads_event);
thread_name = "fil_crypt_thread";
goto wait_suspend_loop;
case SRV_PURGE:
srv_purge_wakeup();
thread_name = "purge thread";
goto wait_suspend_loop;
case SRV_MASTER:
thread_name = "master thread";
goto wait_suspend_loop;
case SRV_WORKER:
thread_name = "worker threads";
goto wait_suspend_loop;
}
/* At this point only page_cleaner should be active. We wait
here to let it complete the flushing of the buffer pools
before proceeding further. */
srv_shutdown_state = SRV_SHUTDOWN_FLUSH_PHASE;
count = 0;
while (buf_page_cleaner_is_active || buf_lru_manager_is_active) {
if (srv_print_verbose_log && count == 0) {
@@ -3672,8 +3681,14 @@ loop:
}
}
if (log_scrub_thread_active) {
ut_ad(!srv_read_only_mode);
os_event_set(log_scrub_event);
}
mutex_enter(&log_sys->mutex);
server_busy = log_sys->n_pending_checkpoint_writes
server_busy = log_scrub_thread_active
|| log_sys->n_pending_checkpoint_writes
#ifdef UNIV_LOG_ARCHIVE
|| log_sys->n_pending_archive_ios
#endif /* UNIV_LOG_ARCHIVE */
@@ -3692,6 +3707,8 @@ loop:
goto loop;
}
ut_ad(!log_scrub_thread_active);
pending_io = buf_pool_check_no_pending_io();
if (pending_io) {
@@ -3727,16 +3744,6 @@ loop:
from the stamps if the previous shutdown was clean. */
log_buffer_flush_to_disk();
/* Check that the background threads stay suspended */
thread_name = srv_any_background_threads_are_active();
if (thread_name != NULL) {
ib_logf(IB_LOG_LEVEL_WARN,
"Background thread %s woke up "
"during shutdown", thread_name);
goto loop;
}
}
srv_shutdown_state = SRV_SHUTDOWN_LAST_PHASE;
@@ -3749,74 +3756,57 @@ loop:
}
fil_close_all_files();
thread_name = srv_any_background_threads_are_active();
ut_a(!thread_name);
return;
}
if (!srv_read_only_mode) {
log_make_checkpoint_at(LSN_MAX, TRUE);
}
mutex_enter(&log_sys->mutex);
mutex_enter(&log_sys->mutex);
tracked_lsn = log_get_tracked_lsn();
tracked_lsn = log_get_tracked_lsn();
lsn = log_sys->lsn;
lsn = log_sys->lsn;
if (lsn != log_sys->last_checkpoint_lsn
|| (srv_track_changed_pages
&& (tracked_lsn != log_sys->last_checkpoint_lsn))
if (lsn != log_sys->last_checkpoint_lsn
|| (srv_track_changed_pages
&& (tracked_lsn != log_sys->last_checkpoint_lsn))
#ifdef UNIV_LOG_ARCHIVE
|| (srv_log_archive_on
&& lsn != log_sys->archived_lsn + LOG_BLOCK_HDR_SIZE)
|| (srv_log_archive_on
&& lsn != log_sys->archived_lsn + LOG_BLOCK_HDR_SIZE)
#endif /* UNIV_LOG_ARCHIVE */
) {
mutex_exit(&log_sys->mutex);
goto loop;
}
#ifdef UNIV_LOG_ARCHIVE
log_archive_close_groups(TRUE);
#endif /* UNIV_LOG_ARCHIVE */
) {
mutex_exit(&log_sys->mutex);
goto loop;
}
#ifdef UNIV_LOG_ARCHIVE
log_archive_close_groups(TRUE);
#endif /* UNIV_LOG_ARCHIVE */
mutex_exit(&log_sys->mutex);
/* Check that the background threads stay suspended */
thread_name = srv_any_background_threads_are_active();
if (thread_name != NULL) {
ib_logf(IB_LOG_LEVEL_WARN,
"Background thread %s woke up during shutdown",
thread_name);
goto loop;
}
if (!srv_read_only_mode) {
fil_flush_file_spaces(FIL_TABLESPACE);
fil_flush_file_spaces(FIL_LOG);
}
/* The call fil_write_flushed_lsn_to_data_files() will pass the buffer
pool: therefore it is essential that the buffer pool has been
completely flushed to disk! (We do not call fil_write... if the
'very fast' shutdown is enabled.) */
/* The call fil_write_flushed_lsn_to_data_files() will
bypass the buffer pool: therefore it is essential that
the buffer pool has been completely flushed to disk! */
if (!buf_all_freed()) {
if (!buf_all_freed()) {
if (srv_print_verbose_log && count > 600) {
ib_logf(IB_LOG_LEVEL_INFO,
"Waiting for dirty buffer pages"
" to be flushed");
count = 0;
}
if (srv_print_verbose_log && count > 600) {
ib_logf(IB_LOG_LEVEL_INFO,
"Waiting for dirty buffer pages to be flushed");
count = 0;
goto loop;
}
goto loop;
} else {
lsn = srv_start_lsn;
}
srv_shutdown_state = SRV_SHUTDOWN_LAST_PHASE;
@@ -4094,6 +4084,10 @@ log_shutdown(void)
mutex_free(&log_sys->mutex);
mutex_free(&log_sys->log_flush_order_mutex);
if (!srv_read_only_mode && srv_scrub_log) {
os_event_free(log_scrub_event);
}
#ifdef UNIV_LOG_ARCHIVE
rw_lock_free(&log_sys->archive_lock);
os_event_free(log_sys->archiving_on);
@@ -4121,11 +4115,6 @@ log_mem_free(void)
}
}
/** Event to wake up the log scrub thread */
UNIV_INTERN os_event_t log_scrub_event = NULL;
UNIV_INTERN ibool srv_log_scrub_thread_active = FALSE;
/*****************************************************************//*
If no log record has been written for a while, fill current log
block with dummy records. */
@@ -4152,17 +4141,11 @@ sleeps again.
@return this function does not return, it calls os_thread_exit() */
extern "C" UNIV_INTERN
os_thread_ret_t
DECLARE_THREAD(log_scrub_thread)(
/*===============================*/
void* arg __attribute__((unused))) /*!< in: a dummy parameter
required by os_thread_create */
DECLARE_THREAD(log_scrub_thread)(void*)
{
ut_ad(!srv_read_only_mode);
srv_log_scrub_thread_active = TRUE;
while(srv_shutdown_state == SRV_SHUTDOWN_NONE)
{
while (srv_shutdown_state < SRV_SHUTDOWN_FLUSH_PHASE) {
/* log scrubbing interval in µs. */
ulonglong interval = 1000*1000*512/innodb_scrub_log_speed;
@@ -4173,7 +4156,7 @@ DECLARE_THREAD(log_scrub_thread)(
os_event_reset(log_scrub_event);
}
srv_log_scrub_thread_active = FALSE;
log_scrub_thread_active = false;
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit and not use return() to exit. */

View File

@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 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
@@ -323,8 +324,7 @@ rec_init_offsets_comp_ordinary(
stored in one byte for 0..127. The length
will be encoded in two bytes when it is 128 or
more, or when the field is stored externally. */
if (UNIV_UNLIKELY(col->len > 255 -
prtype_get_compression_extra(col->prtype))
if (UNIV_UNLIKELY(col->len > 255)
|| UNIV_UNLIKELY(col->mtype
== DATA_BLOB)) {
if (len & 0x80) {
@@ -849,8 +849,7 @@ rec_get_converted_size_comp_prefix_low(
((col->mtype == DATA_VARCHAR || col->mtype == DATA_BINARY
|| col->mtype == DATA_VARMYSQL)
&& (col->len == 0
|| len <= col->len +
prtype_get_compression_extra(col->prtype))));
|| len <= col->len)));
fixed_len = field->fixed_len;
if (temp && fixed_len
@@ -882,8 +881,7 @@ rec_get_converted_size_comp_prefix_low(
ut_ad(col->len >= 256 || col->mtype == DATA_BLOB);
extra_size += 2;
} else if (len < 128
|| (col->len < 256 -
prtype_get_compression_extra(col->prtype)
|| (col->len < 256
&& col->mtype != DATA_BLOB)) {
extra_size++;
} else {
@@ -1279,16 +1277,12 @@ rec_convert_dtuple_to_rec_comp(
*lens-- = (byte) (len >> 8) | 0xc0;
*lens-- = (byte) len;
} else {
ut_ad(len <= dtype_get_len(type) +
prtype_get_compression_extra(
dtype_get_prtype(type))
ut_ad(len <= dtype_get_len(type)
|| dtype_get_mtype(type) == DATA_BLOB
|| !strcmp(index->name,
FTS_INDEX_TABLE_IND_NAME));
if (len < 128
|| (dtype_get_len(type) < 256 -
prtype_get_compression_extra(
dtype_get_prtype(type))
|| (dtype_get_len(type) < 256
&& dtype_get_mtype(type) != DATA_BLOB)) {
*lens-- = (byte) len;

View File

@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 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
@@ -623,8 +624,7 @@ row_merge_buf_add(
((col->mtype == DATA_VARCHAR || col->mtype == DATA_BINARY
|| col->mtype == DATA_VARMYSQL)
&& (col->len == 0
|| len <= col->len +
prtype_get_compression_extra(col->prtype))));
|| len <= col->len)));
fixed_len = ifield->fixed_len;
if (fixed_len && !dict_table_is_comp(index->table)
@@ -653,8 +653,7 @@ row_merge_buf_add(
} else if (dfield_is_ext(field)) {
extra_size += 2;
} else if (len < 128
|| (col->len < 256 -
prtype_get_compression_extra(col->prtype)
|| (col->len < 256
&& col->mtype != DATA_BLOB)) {
extra_size++;
} else {

View File

@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 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
@@ -71,48 +72,6 @@ Created 9/17/2000 Heikki Tuuri
/** Provide optional 4.x backwards compatibility for 5.0 and above */
UNIV_INTERN ibool row_rollback_on_timeout = FALSE;
/**
Z_NO_COMPRESSION = 0
Z_BEST_SPEED = 1
Z_BEST_COMPRESSION = 9
Z_DEFAULT_COMPRESSION = -1
Compression level to be used by zlib for compressed-blob columns.
Settable by user.
*/
UNIV_INTERN uint srv_compressed_columns_zip_level = DEFAULT_COMPRESSION_LEVEL;
/**
(Z_FILTERED | Z_HUFFMAN_ONLY | Z_RLE | Z_FIXED | Z_DEFAULT_STRATEGY)
The strategy parameter is used to tune the compression algorithm. Use the
value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only
(no string match), or Z_RLE to limit match distances to one
(run-length encoding). Filtered data consists mostly of small values with a
somewhat random distribution. In this case, the compression algorithm is
tuned to compress them better.
The effect of Z_FILTERED is to force more Huffman coding and less string
matching; it is somewhat intermediate between Z_DEFAULT_STRATEGY and
Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as Z_HUFFMAN_ONLY,
but give better compression for PNG image data. The strategy parameter only
affects the compression ratio but not the correctness of the compressed
output even if it is not set appropriately. Z_FIXED prevents the use of
dynamic Huffman codes, allowing for a simpler decoder for special
applications.
*/
const uint srv_compressed_columns_zlib_strategy = Z_DEFAULT_STRATEGY;
/** Compress the column if the data length exceeds this value. */
UNIV_INTERN ulong srv_compressed_columns_threshold = 96;
/**
Determine if zlib needs to compute adler32 value for the compressed data.
This variables is similar to page_zip_zlib_wrap, but only used by
compressed blob columns.
*/
const bool srv_compressed_columns_zlib_wrap = true;
/**
Determine if zlib will use custom memory allocation functions based on
InnoDB memory heap routines (mem_heap_t*).
*/
const bool srv_compressed_columns_zlib_use_heap = false;
/** Chain node of the list of tables to drop in the background. */
struct row_mysql_drop_t{
char* table_name; /*!< table name */
@@ -216,17 +175,6 @@ row_mysql_prebuilt_free_blob_heap(
prebuilt->blob_heap = NULL;
}
/** Frees the compress heap in prebuilt when no longer needed. */
UNIV_INTERN
void
row_mysql_prebuilt_free_compress_heap(
row_prebuilt_t* prebuilt) /*!< in: prebuilt struct of a
ha_innobase:: table handle */
{
mem_heap_free(prebuilt->compress_heap);
prebuilt->compress_heap = NULL;
}
/*******************************************************************//**
Stores a >= 5.0.3 format true VARCHAR length to dest, in the MySQL row
format.
@@ -283,425 +231,6 @@ row_mysql_read_true_varchar(
return(field + 1);
}
/**
Compressed BLOB header format:
---------------------------------------------------------------
| reserved | wrap | algorithm | len-len | compressed | unused |
| [1] | [1] | [5] | [3] | [1] | [5] |
---------------------------------------------------------------
| 0 0 | 1 1 | 2 6 | 7 9 | 10 10 | 11 15 |
---------------------------------------------------------------
* 'reserved' bit is planned to be used in future versions of the BLOB
header. In this version it must always be
'default_zip_column_reserved_value' (0).
* 'wrap' identifies if compression algorithm calculated a checksum
(adler32 in case of zlib) and appended it to the compressed data.
* 'algorithm' identifies which algoritm was used to compress this BLOB.
Currently, the only value 'default_zip_column_algorithm_value' (0) is
supported.
* 'len-len' field identifies the length of the column length data portion
followed by this header (see below).
* If 'compressed' bit is set to 1, then this header is immediately followed
by 1..8 bytes (depending on the value of 'len-len' bitfield) which
determine original (uncompressed) block size. These 'len-len' bytes are
followed by compressed representation of the original data.
* If 'compressed' bit is set to 0, every other bitfield ('wrap',
'algorithm' and 'le-len') must be ignored. In this case the header is
immediately followed by uncompressed (original) data.
*/
/**
Currently the only supported value for the 'reserved' field is
false (0).
*/
static const bool default_zip_column_reserved_value = false;
/**
Currently the only supported value for the 'algorithm' field is 0, which
means 'zlib'.
*/
static const uint default_zip_column_algorithm_value = 0;
static const size_t zip_column_prefix_max_length =
ZIP_COLUMN_HEADER_LENGTH + 8;
static const size_t zip_column_header_length = ZIP_COLUMN_HEADER_LENGTH;
/* 'reserved', bit 0 */
static const uint zip_column_reserved = 0;
/* 0000 0000 0000 0001 */
static const uint zip_column_reserved_mask = 0x0001;
/* 'wrap', bit 1 */
static const uint zip_column_wrap = 1;
/* 0000 0000 0000 0010 */
static const uint zip_column_wrap_mask = 0x0002;
/* 'algorithm', bit 2,3,4,5,6 */
static const uint zip_column_algorithm = 2;
/* 0000 0000 0111 1100 */
static const uint zip_column_algorithm_mask = 0x007C;
/* 'len-len', bit 7,8,9 */
static const uint zip_column_data_length = 7;
/* 0000 0011 1000 0000 */
static const uint zip_column_data_length_mask = 0x0380;
/* 'compressed', bit 10 */
static const uint zip_column_compressed = 10;
/* 0000 0100 0000 0000 */
static const uint zip_column_compressed_mask = 0x0400;
/** Updates compressed block header with the given components */
static void
column_set_compress_header(
byte* data,
bool compressed,
ulint lenlen,
uint alg,
bool wrap,
bool reserved)
{
ulint header = 0;
header |= (compressed << zip_column_compressed);
header |= (lenlen << zip_column_data_length);
header |= (alg << zip_column_algorithm);
header |= (wrap << zip_column_wrap);
header |= (reserved << zip_column_reserved);
mach_write_to_2(data, header);
}
/** Parse compressed block header into components */
static void
column_get_compress_header(
const byte* data,
bool* compressed,
ulint* lenlen,
uint* alg,
bool* wrap,
bool* reserved
)
{
ulint header = mach_read_from_2(data);
*compressed = ((header & zip_column_compressed_mask) >>
zip_column_compressed);
*lenlen = ((header & zip_column_data_length_mask) >>
zip_column_data_length);
*alg = ((header & zip_column_algorithm_mask) >>
zip_column_algorithm);
*wrap = ((header & zip_column_wrap_mask) >>
zip_column_wrap);
*reserved = ((header & zip_column_reserved_mask) >>
zip_column_reserved);
}
/** Allocate memory for zlib. */
static
void*
column_zip_zalloc(
void* opaque, /*!< in/out: memory heap */
uInt items, /*!< in: number of items to allocate */
uInt size) /*!< in: size of an item in bytes */
{
return(mem_heap_zalloc(static_cast<mem_heap_t*>(opaque),
items * size));
}
/** Deallocate memory for zlib. */
static
void
column_zip_free(
void* opaque MY_ATTRIBUTE((unused)), /*!< in: memory heap */
void* address MY_ATTRIBUTE((unused))) /*!< in: object to free */
{
}
/** Configure the zlib allocator to use the given memory heap. */
UNIV_INTERN
void
column_zip_set_alloc(
void* stream, /*!< in/out: zlib stream */
mem_heap_t* heap) /*!< in: memory heap to use */
{
z_stream* strm = static_cast<z_stream*>(stream);
if (srv_compressed_columns_zlib_use_heap) {
strm->zalloc = column_zip_zalloc;
strm->zfree = column_zip_free;
strm->opaque = heap;
} else {
strm->zalloc = (alloc_func)0;
strm->zfree = (free_func)0;
strm->opaque = (voidpf)0;
}
}
/** Compress blob/text/varchar column using zlib
@return pointer to the compressed data */
byte*
row_compress_column(
const byte* data, /*!< in: data in mysql(uncompressed)
format */
ulint *len, /*!< in: data length; out: length of
compressed data*/
ulint lenlen, /*!< in: bytes used to store the length of
data */
const byte* dict_data,
/*!< in: optional dictionary data used for
compression */
ulint dict_data_len,
/*!< in: optional dictionary data length */
row_prebuilt_t* prebuilt)
/*!< in: use prebuilt->compress_heap only
here*/
{
int err = 0;
ulint comp_len = *len;
ulint buf_len = *len + zip_column_prefix_max_length;
byte* buf;
byte* ptr;
z_stream c_stream;
bool wrap = srv_compressed_columns_zlib_wrap;
int window_bits = wrap ? MAX_WBITS : -MAX_WBITS;
if (!prebuilt->compress_heap) {
prebuilt->compress_heap =
mem_heap_create(max(UNIV_PAGE_SIZE, buf_len));
}
buf = static_cast<byte*>(mem_heap_zalloc(
prebuilt->compress_heap,buf_len));
if (*len < srv_compressed_columns_threshold ||
srv_compressed_columns_zip_level == Z_NO_COMPRESSION)
goto do_not_compress;
ptr = buf + zip_column_header_length + lenlen;
/*init deflate object*/
c_stream.next_in = const_cast<Bytef*>(data);
c_stream.avail_in = *len;
c_stream.next_out = ptr;
c_stream.avail_out = comp_len;
column_zip_set_alloc(&c_stream, prebuilt->compress_heap);
err = deflateInit2(&c_stream, srv_compressed_columns_zip_level,
Z_DEFLATED, window_bits, MAX_MEM_LEVEL,
srv_compressed_columns_zlib_strategy);
ut_a(err == Z_OK);
if (dict_data != 0 && dict_data_len != 0) {
err = deflateSetDictionary(&c_stream, dict_data,
dict_data_len);
ut_a(err == Z_OK);
}
err = deflate(&c_stream, Z_FINISH);
if (err != Z_STREAM_END) {
deflateEnd(&c_stream);
if (err == Z_OK)
err = Z_BUF_ERROR;
} else {
comp_len = c_stream.total_out;
err = deflateEnd(&c_stream);
}
switch (err) {
case Z_OK:
break;
case Z_BUF_ERROR:
/* data after compress is larger than uncompressed data*/
break;
default:
ib_logf(IB_LOG_LEVEL_ERROR,
"failed to compress the column, error: %d\n", err);
}
/* make sure the compressed data size is smaller than
uncompressed data */
if (err == Z_OK &&
*len > (comp_len + zip_column_header_length + lenlen)) {
column_set_compress_header(buf, true, lenlen - 1,
default_zip_column_algorithm_value, wrap,
default_zip_column_reserved_value);
ptr = buf + zip_column_header_length;
/*store the uncompressed data length*/
switch (lenlen) {
case 1:
mach_write_to_1(ptr, *len);
break;
case 2:
mach_write_to_2(ptr, *len);
break;
case 3:
mach_write_to_3(ptr, *len);
break;
case 4:
mach_write_to_4(ptr, *len);
break;
default:
ut_error;
}
*len = comp_len + zip_column_header_length + lenlen;
return buf;
}
do_not_compress:
ptr = buf;
column_set_compress_header(ptr, false, 0,
default_zip_column_algorithm_value, false,
default_zip_column_reserved_value);
ptr += zip_column_header_length;
memcpy(ptr, data, *len);
*len += zip_column_header_length;
return buf;
}
/** Uncompress blob/text/varchar column using zlib
@return pointer to the uncompressed data */
const byte*
row_decompress_column(
const byte* data, /*!< in: data in innodb(compressed) format */
ulint *len, /*!< in: data length; out: length of
decompressed data*/
const byte* dict_data,
/*!< in: optional dictionary data used for
decompression */
ulint dict_data_len,
/*!< in: optional dictionary data length */
row_prebuilt_t* prebuilt)
/*!< in: use prebuilt->compress_heap only
here*/
{
ulint buf_len = 0;
byte* buf;
int err = 0;
int window_bits = 0;
z_stream d_stream;
bool is_compressed = false;
bool wrap = false;
bool reserved = false;
ulint lenlen = 0;
uint alg = 0;
ut_ad(*len != ULINT_UNDEFINED);
ut_ad(*len >= zip_column_header_length);
column_get_compress_header(data, &is_compressed, &lenlen, &alg,
&wrap, &reserved);
if (reserved != default_zip_column_reserved_value) {
ib_logf(IB_LOG_LEVEL_FATAL,
"unsupported compressed BLOB header format\n");
}
if (alg != default_zip_column_algorithm_value) {
ib_logf(IB_LOG_LEVEL_FATAL,
"unsupported 'algorithm' value in the"
" compressed BLOB header\n");
}
ut_a(lenlen < 4);
data += zip_column_header_length;
if (!is_compressed) { /* column not compressed */
*len -= zip_column_header_length;
return data;
}
lenlen++;
ulint comp_len = *len - zip_column_header_length - lenlen;
ulint uncomp_len = 0;
switch (lenlen) {
case 1:
uncomp_len = mach_read_from_1(data);
break;
case 2:
uncomp_len = mach_read_from_2(data);
break;
case 3:
uncomp_len = mach_read_from_3(data);
break;
case 4:
uncomp_len = mach_read_from_4(data);
break;
default:
ut_error;
}
data += lenlen;
/* data is compressed, decompress it*/
if (!prebuilt->compress_heap) {
prebuilt->compress_heap =
mem_heap_create(max(UNIV_PAGE_SIZE, uncomp_len));
}
buf_len = uncomp_len;
buf = static_cast<byte*>(mem_heap_zalloc(
prebuilt->compress_heap, buf_len));
/* init d_stream */
d_stream.next_in = const_cast<Bytef*>(data);
d_stream.avail_in = comp_len;
d_stream.next_out = buf;
d_stream.avail_out = buf_len;
column_zip_set_alloc(&d_stream, prebuilt->compress_heap);
window_bits = wrap ? MAX_WBITS : -MAX_WBITS;
err = inflateInit2(&d_stream, window_bits);
ut_a(err == Z_OK);
err = inflate(&d_stream, Z_FINISH);
if (err == Z_NEED_DICT) {
ut_a(dict_data != 0 && dict_data_len != 0);
err = inflateSetDictionary(&d_stream, dict_data,
dict_data_len);
ut_a(err == Z_OK);
err = inflate(&d_stream, Z_FINISH);
}
if (err != Z_STREAM_END) {
inflateEnd(&d_stream);
if (err == Z_BUF_ERROR && d_stream.avail_in == 0)
err = Z_DATA_ERROR;
} else {
buf_len = d_stream.total_out;
err = inflateEnd(&d_stream);
}
switch (err) {
case Z_OK:
break;
case Z_BUF_ERROR:
ib_logf(IB_LOG_LEVEL_FATAL,
"zlib buf error, this shouldn't happen\n");
break;
default:
ib_logf(IB_LOG_LEVEL_FATAL,
"failed to decompress column, error: %d\n", err);
}
if (err == Z_OK) {
if (buf_len != uncomp_len) {
ib_logf(IB_LOG_LEVEL_FATAL,
"failed to decompress blob column, may"
" be corrupted\n");
}
*len = buf_len;
return buf;
}
*len -= (zip_column_header_length + lenlen);
return data;
}
/*******************************************************************//**
Stores a reference to a BLOB in the MySQL format. */
UNIV_INTERN
@@ -715,21 +244,10 @@ row_mysql_store_blob_ref(
to 4 bytes */
const void* data, /*!< in: BLOB data; if the value to store
is SQL NULL this should be NULL pointer */
ulint len, /*!< in: BLOB length; if the value to store
ulint len) /*!< in: BLOB length; if the value to store
is SQL NULL this should be 0; remember
also to set the NULL bit in the MySQL record
header! */
bool need_decompression,
/*!< in: if the data need to be compressed*/
const byte* dict_data,
/*!< in: optional compression dictionary
data */
ulint dict_data_len,
/*!< in: optional compression dictionary data
length */
row_prebuilt_t* prebuilt)
/*<! in: use prebuilt->compress_heap only
here */
{
/* MySQL might assume the field is set to zero except the length and
the pointer fields */
@@ -741,27 +259,11 @@ row_mysql_store_blob_ref(
In 32-bit architectures we only use the first 4 bytes of the pointer
slot. */
ut_a(col_len - 8 > 1 ||
len < 256 +
(need_decompression ? ZIP_COLUMN_HEADER_LENGTH : 0));
ut_a(col_len - 8 > 2 ||
len < 256 * 256 +
(need_decompression ? ZIP_COLUMN_HEADER_LENGTH : 0));
ut_a(col_len - 8 > 3 ||
len < 256 * 256 * 256 +
(need_decompression ? ZIP_COLUMN_HEADER_LENGTH : 0));
const byte *ptr = NULL;
if (need_decompression)
ptr = row_decompress_column((const byte*)data, &len,
dict_data, dict_data_len, prebuilt);
if (ptr)
memcpy(dest + col_len - 8, &ptr, sizeof ptr);
else
memcpy(dest + col_len - 8, &data, sizeof data);
ut_a(col_len - 8 > 1 || len < 256);
ut_a(col_len - 8 > 2 || len < 256 * 256);
ut_a(col_len - 8 > 3 || len < 256 * 256 * 256);
memcpy(dest + col_len - 8, &data, sizeof data);
mach_write_to_n_little_endian(dest, col_len - 8, len);
}
@@ -775,32 +277,15 @@ row_mysql_read_blob_ref(
ulint* len, /*!< out: BLOB length */
const byte* ref, /*!< in: BLOB reference in the
MySQL format */
ulint col_len, /*!< in: BLOB reference length
ulint col_len) /*!< in: BLOB reference length
(not BLOB length) */
bool need_compression,
/*!< in: if the data need to be
compressed*/
const byte* dict_data, /*!< in: optional compression
dictionary data */
ulint dict_data_len, /*!< in: optional compression
dictionary data length */
row_prebuilt_t* prebuilt) /*!< in: use prebuilt->compress_heap
only here */
{
byte* data = NULL;
byte* ptr = NULL;
*len = mach_read_from_n_little_endian(ref, col_len - 8);
memcpy(&data, ref + col_len - 8, sizeof data);
if (need_compression) {
ptr = row_compress_column(data, len, col_len - 8, dict_data,
dict_data_len, prebuilt);
if (ptr)
data = ptr;
}
return(data);
}
@@ -883,16 +368,7 @@ row_mysql_store_col_in_innobase_format(
necessarily the length of the actual
payload data; if the column is a true
VARCHAR then this is irrelevant */
ulint comp, /*!< in: nonzero=compact format */
bool need_compression,
/*!< in: if the data need to be
compressed*/
const byte* dict_data, /*!< in: optional compression
dictionary data */
ulint dict_data_len, /*!< in: optional compression
dictionary data length */
row_prebuilt_t* prebuilt) /*!< in: use prebuilt->compress_heap
only here */
ulint comp) /*!< in: nonzero=compact format */
{
const byte* ptr = mysql_data;
const dtype_t* dtype;
@@ -945,14 +421,8 @@ row_mysql_store_col_in_innobase_format(
lenlen = 2;
}
const byte* tmp_ptr = row_mysql_read_true_varchar(
ptr = row_mysql_read_true_varchar(
&col_len, mysql_data, lenlen);
if (need_compression)
ptr = row_compress_column(tmp_ptr, &col_len,
lenlen, dict_data, dict_data_len,
prebuilt);
else
ptr = tmp_ptr;
} else {
/* Remove trailing spaces from old style VARCHAR
columns. */
@@ -1034,9 +504,7 @@ row_mysql_store_col_in_innobase_format(
}
} else if (type == DATA_BLOB && row_format_col) {
ptr = row_mysql_read_blob_ref(&col_len, mysql_data, col_len,
need_compression, dict_data, dict_data_len,
prebuilt);
ptr = row_mysql_read_blob_ref(&col_len, mysql_data, col_len);
}
dfield_set_data(dfield, ptr, col_len);
@@ -1094,11 +562,7 @@ row_mysql_convert_row_to_innobase(
TRUE, /* MySQL row format data */
mysql_rec + templ->mysql_col_offset,
templ->mysql_col_len,
dict_table_is_comp(prebuilt->table),
templ->compressed,
reinterpret_cast<const byte*>(
templ->zip_dict_data.str),
templ->zip_dict_data.length, prebuilt);
dict_table_is_comp(prebuilt->table));
next_column:
;
}
@@ -1444,10 +908,6 @@ row_prebuilt_free(
mem_heap_free(prebuilt->blob_heap);
}
if (prebuilt->compress_heap) {
mem_heap_free(prebuilt->compress_heap);
}
if (prebuilt->old_vers_heap) {
mem_heap_free(prebuilt->old_vers_heap);
}
@@ -1883,9 +1343,6 @@ row_insert_for_mysql(
return(DB_READ_ONLY);
}
if (UNIV_LIKELY_NULL(prebuilt->compress_heap))
mem_heap_empty(prebuilt->compress_heap);
trx->op_info = "inserting";
row_mysql_delay_if_needed();
@@ -3460,8 +2917,6 @@ row_mysql_table_id_reassign(
" WHERE TABLE_ID = :old_id;\n"
"UPDATE SYS_INDEXES SET TABLE_ID = :new_id\n"
" WHERE TABLE_ID = :old_id;\n"
"UPDATE SYS_ZIP_DICT_COLS SET TABLE_ID = :new_id_narrow\n"
" WHERE TABLE_ID = :old_id_narrow;\n"
"END;\n", FALSE, trx);
return(err);
@@ -4294,9 +3749,6 @@ next_rec:
"UPDATE SYS_INDEXES"
" SET TABLE_ID = :new_id, SPACE = :new_space\n"
" WHERE TABLE_ID = :old_id;\n"
"UPDATE SYS_ZIP_DICT_COLS\n"
" SET TABLE_ID = :new_id_narrow\n"
" WHERE TABLE_ID = :old_id_narrow;\n"
"END;\n"
, FALSE, trx);
@@ -4948,19 +4400,6 @@ row_drop_table_for_mysql(
filepath = fil_make_ibd_name(tablename, false);
}
/* Remove all compression dictionary references for the
table */
err = dict_create_remove_zip_dict_references_for_table(
table->id, trx);
if (err != DB_SUCCESS) {
ib_logf(IB_LOG_LEVEL_ERROR, "Error: (%s) not "
"able to remove compression dictionary "
"references for table %s", ut_strerr(err),
tablename);
goto funct_exit;
}
if (dict_table_has_fts_index(table)
|| DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID)) {
ut_ad(table->n_ref_count == 0);

View File

@@ -2,7 +2,7 @@
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2015, MariaDB Corporation.
Copyright (c) 2015, 2017, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -2461,8 +2461,7 @@ row_sel_convert_mysql_key_to_innobase(
/* MySQL key value format col */
FALSE,
key_ptr + data_offset, data_len,
dict_table_is_comp(index->table),
false, 0, 0 ,0);
dict_table_is_comp(index->table));
ut_a(buf <= original_buf + buf_len);
}
@@ -2556,15 +2555,15 @@ row_sel_store_row_id_to_prebuilt(
#ifdef UNIV_DEBUG
/** Convert a non-SQL-NULL field from Innobase format to MySQL format. */
# define row_sel_field_store_in_mysql_format( \
dest,templ,idx,field,src,len,prebuilt) \
dest,templ,idx,field,src,len) \
row_sel_field_store_in_mysql_format_func \
(dest,templ,idx,field,src,len, prebuilt)
(dest,templ,idx,field,src,len)
#else /* UNIV_DEBUG */
/** Convert a non-SQL-NULL field from Innobase format to MySQL format. */
# define row_sel_field_store_in_mysql_format( \
dest,templ,idx,field,src,len,prebuilt) \
dest,templ,idx,field,src,len) \
row_sel_field_store_in_mysql_format_func \
(dest,templ,src,len, prebuilt)
(dest,templ,src,len)
#endif /* UNIV_DEBUG */
/**************************************************************//**
@@ -2594,10 +2593,7 @@ row_sel_field_store_in_mysql_format_func(
templ->icp_rec_field_no */
#endif /* UNIV_DEBUG */
const byte* data, /*!< in: data to store */
ulint len, /*!< in: length of the data */
row_prebuilt_t* prebuilt)
/*!< in: use prebuilt->compress_heap
only here */
ulint len) /*!< in: length of the data */
{
byte* ptr;
#ifdef UNIV_DEBUG
@@ -2641,15 +2637,6 @@ row_sel_field_store_in_mysql_format_func(
field_end = dest + templ->mysql_col_len;
if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
/* If this is a compressed column,
decompress it first */
if (templ->compressed)
data = row_decompress_column(data, &len,
reinterpret_cast<const byte*>(
templ->zip_dict_data.str),
templ->zip_dict_data.length,
prebuilt);
/* This is a >= 5.0.3 type true VARCHAR. Store the
length of the data to the first byte or the first
two bytes of dest. */
@@ -2700,11 +2687,7 @@ row_sel_field_store_in_mysql_format_func(
already copied to the buffer in row_sel_store_mysql_rec */
row_mysql_store_blob_ref(dest, templ->mysql_col_len, data,
len, templ->compressed,
reinterpret_cast<const byte*>(
templ->zip_dict_data.str),
templ->zip_dict_data.length,
prebuilt);
len);
break;
case DATA_MYSQL:
@@ -2857,7 +2840,7 @@ row_sel_store_mysql_field_func(
row_sel_field_store_in_mysql_format(
mysql_rec + templ->mysql_col_offset,
templ, index, field_no, data, len, prebuilt);
templ, index, field_no, data, len);
if (heap != prebuilt->blob_heap) {
mem_heap_free(heap);
@@ -2907,7 +2890,7 @@ row_sel_store_mysql_field_func(
row_sel_field_store_in_mysql_format(
mysql_rec + templ->mysql_col_offset,
templ, index, field_no, data, len, prebuilt);
templ, index, field_no, data, len);
}
ut_ad(len != UNIV_SQL_NULL);
@@ -2955,9 +2938,6 @@ row_sel_store_mysql_rec(
prebuilt->blob_heap = NULL;
}
if (UNIV_LIKELY_NULL(prebuilt->compress_heap))
mem_heap_empty(prebuilt->compress_heap);
for (i = 0; i < prebuilt->n_template; i++) {
const mysql_row_templ_t*templ = &prebuilt->mysql_template[i];
const ulint field_no

View File

@@ -3,7 +3,7 @@
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2016, MariaDB Corporation.
Copyright (c) 2013, 2017, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -61,7 +61,6 @@ Created 10/8/1995 Heikki Tuuri
#include "btr0sea.h"
#include "dict0load.h"
#include "dict0boot.h"
#include "dict0stats_bg.h" /* dict_stats_event */
#include "srv0start.h"
#include "row0mysql.h"
#include "row0log.h"
@@ -107,15 +106,14 @@ UNIV_INTERN long long srv_kill_idle_transaction = 0;
in microseconds, in order to reduce the lagging of the purge thread. */
UNIV_INTERN ulint srv_dml_needed_delay = 0;
UNIV_INTERN ibool srv_monitor_active = FALSE;
UNIV_INTERN ibool srv_error_monitor_active = FALSE;
UNIV_INTERN bool srv_monitor_active;
UNIV_INTERN bool srv_error_monitor_active;
UNIV_INTERN ibool srv_buf_dump_thread_active = FALSE;
UNIV_INTERN bool srv_buf_dump_thread_active;
UNIV_INTERN ibool srv_dict_stats_thread_active = FALSE;
UNIV_INTERN bool srv_dict_stats_thread_active;
UNIV_INTERN ibool srv_log_scrub_active = FALSE;
UNIV_INTERN my_bool srv_scrub_log = FALSE;
UNIV_INTERN my_bool srv_scrub_log;
UNIV_INTERN const char* srv_main_thread_op_info = "";
@@ -2095,11 +2093,7 @@ A thread which prints the info output by various InnoDB monitors.
@return a dummy parameter */
extern "C" UNIV_INTERN
os_thread_ret_t
DECLARE_THREAD(srv_monitor_thread)(
/*===============================*/
void* arg MY_ATTRIBUTE((unused)))
/*!< in: a dummy parameter required by
os_thread_create */
DECLARE_THREAD(srv_monitor_thread)(void*)
{
ib_int64_t sig_count;
double time_elapsed;
@@ -2120,9 +2114,7 @@ DECLARE_THREAD(srv_monitor_thread)(
#ifdef UNIV_PFS_THREAD
pfs_register_thread(srv_monitor_thread_key);
#endif /* UNIV_PFS_THREAD */
srv_monitor_active = TRUE;
UT_NOT_USED(arg);
srv_last_monitor_time = ut_time();
last_table_monitor_time = ut_time();
last_tablespace_monitor_time = ut_time();
@@ -2254,7 +2246,7 @@ loop:
goto loop;
exit_func:
srv_monitor_active = FALSE;
srv_monitor_active = false;
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit and not use return() to exit. */
@@ -2272,11 +2264,7 @@ we should avoid waiting any mutexes in this function!
@return a dummy parameter */
extern "C" UNIV_INTERN
os_thread_ret_t
DECLARE_THREAD(srv_error_monitor_thread)(
/*=====================================*/
void* arg MY_ATTRIBUTE((unused)))
/*!< in: a dummy parameter required by
os_thread_create */
DECLARE_THREAD(srv_error_monitor_thread)(void*)
{
/* number of successive fatal timeouts observed */
ulint fatal_cnt = 0;
@@ -2302,7 +2290,6 @@ DECLARE_THREAD(srv_error_monitor_thread)(
#ifdef UNIV_PFS_THREAD
pfs_register_thread(srv_error_monitor_thread_key);
#endif /* UNIV_PFS_THREAD */
srv_error_monitor_active = TRUE;
loop:
/* Try to track a strange bug reported by Harald Fuchs and others,
@@ -2418,7 +2405,7 @@ rescan_idle:
goto loop;
}
srv_error_monitor_active = FALSE;
srv_error_monitor_active = false;
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit and not use return() to exit. */
@@ -2482,44 +2469,6 @@ srv_get_active_thread_type(void)
return(ret);
}
/**********************************************************************//**
Check whether any background thread are active. If so print which thread
is active. Send the threads wakeup signal.
@return name of thread that is active or NULL */
UNIV_INTERN
const char*
srv_any_background_threads_are_active(void)
/*=======================================*/
{
const char* thread_active = NULL;
if (srv_read_only_mode) {
return(NULL);
} else if (srv_error_monitor_active) {
thread_active = "srv_error_monitor_thread";
} else if (lock_sys->timeout_thread_active) {
thread_active = "srv_lock_timeout thread";
} else if (srv_monitor_active) {
thread_active = "srv_monitor_thread";
} else if (srv_buf_dump_thread_active) {
thread_active = "buf_dump_thread";
} else if (srv_dict_stats_thread_active) {
thread_active = "dict_stats_thread";
} else if (srv_scrub_log && srv_log_scrub_thread_active) {
thread_active = "log_scrub_thread";
}
os_event_set(srv_error_event);
os_event_set(srv_monitor_event);
os_event_set(srv_buf_dump_event);
os_event_set(lock_sys->timeout_event);
os_event_set(dict_stats_event);
if (srv_scrub_log)
os_event_set(log_scrub_event);
return(thread_active);
}
/******************************************************************//**
A thread which follows the redo log and outputs the changed page bitmap.
@return a dummy value */

View File

@@ -3,7 +3,7 @@
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2016, MariaDB Corporation
Copyright (c) 2013, 2017, MariaDB Corporation
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -2404,11 +2404,6 @@ files_checked:
dict_stats_thread_init();
}
if (!srv_read_only_mode && srv_scrub_log) {
/* TODO(minliz): have/use log_scrub_thread_init() instead? */
log_scrub_event = os_event_create();
}
trx_sys_file_format_init();
trx_sys_create();
@@ -2751,14 +2746,17 @@ files_checked:
lock_wait_timeout_thread,
NULL, thread_ids + 2 + SRV_MAX_N_IO_THREADS);
thread_started[2 + SRV_MAX_N_IO_THREADS] = true;
lock_sys->timeout_thread_active = true;
/* Create the thread which warns of long semaphore waits */
srv_error_monitor_active = true;
thread_handles[3 + SRV_MAX_N_IO_THREADS] = os_thread_create(
srv_error_monitor_thread,
NULL, thread_ids + 3 + SRV_MAX_N_IO_THREADS);
thread_started[3 + SRV_MAX_N_IO_THREADS] = true;
/* Create the thread which prints InnoDB monitor info */
srv_monitor_active = true;
thread_handles[4 + SRV_MAX_N_IO_THREADS] = os_thread_create(
srv_monitor_thread,
NULL, thread_ids + 4 + SRV_MAX_N_IO_THREADS);
@@ -2780,12 +2778,6 @@ files_checked:
}
}
/* Create the SYS_ZIP_DICT system table */
err = dict_create_or_check_sys_zip_dict();
if (err != DB_SUCCESS) {
return(err);
}
srv_is_being_started = FALSE;
ut_a(trx_purge_state() == PURGE_STATE_INIT);
@@ -3008,6 +3000,8 @@ files_checked:
/* Create the buffer pool dump/load thread */
buf_dump_thread_handle=
os_thread_create(buf_dump_thread, NULL, NULL);
srv_buf_dump_thread_active = true;
buf_dump_thread_started = true;
#ifdef WITH_WSREP
} else {
@@ -3018,7 +3012,9 @@ files_checked:
#endif /* WITH_WSREP */
/* Create the dict stats gathering thread */
dict_stats_thread_handle = os_thread_create(dict_stats_thread, NULL, NULL);
dict_stats_thread_handle = os_thread_create(
dict_stats_thread, NULL, NULL);
srv_dict_stats_thread_active = true;
dict_stats_thread_started = true;
/* Create the thread that will optimize the FTS sub-system. */
@@ -3028,10 +3024,6 @@ files_checked:
fil_system_enter();
fil_crypt_threads_init();
fil_system_exit();
/* Create the log scrub thread */
if (srv_scrub_log)
os_thread_create(log_scrub_thread, NULL, NULL);
}
/* Init data for datafile scrub threads */
@@ -3100,9 +3092,6 @@ innobase_shutdown_for_mysql(void)
fts_optimize_start_shutdown();
fts_optimize_end();
/* Shutdown key rotation threads */
fil_crypt_threads_end();
}
/* 1. Flush the buffer pool to disk, write the current lsn to
@@ -3205,14 +3194,6 @@ innobase_shutdown_for_mysql(void)
if (!srv_read_only_mode) {
dict_stats_thread_deinit();
if (srv_scrub_log) {
/* TODO(minliz): have/use log_scrub_thread_deinit() instead? */
os_event_free(log_scrub_event);
log_scrub_event = NULL;
}
}
if (!srv_read_only_mode) {
fil_crypt_threads_cleanup();
}

View File

@@ -285,18 +285,33 @@ trx_purge_add_update_undo_to_history(
}
}
/**********************************************************************//**
Frees an undo log segment which is in the history list. Cuts the end of the
history list at the youngest undo log in this segment. */
/** Remove undo log header from the history list.
@param[in,out] rseg_hdr rollback segment header
@param[in] log_hdr undo log segment header
@param[in,out] mtr mini transaction. */
static
void
trx_purge_remove_log_hdr(
trx_rsegf_t* rseg_hdr,
trx_ulogf_t* log_hdr,
mtr_t* mtr)
{
flst_remove(rseg_hdr + TRX_RSEG_HISTORY,
log_hdr + TRX_UNDO_HISTORY_NODE, mtr);
os_atomic_decrement_ulint(&trx_sys->rseg_history_len, 1);
}
/** Frees an undo log segment which is in the history list. Removes the
undo log hdr from the history list.
@param[in,out] rseg rollback segment
@param[in] hdr_addr file address of log_hdr
@param[in] noredo skip redo logging. */
static
void
trx_purge_free_segment(
/*===================*/
trx_rseg_t* rseg, /*!< in: rollback segment */
fil_addr_t hdr_addr, /*!< in: the file address of log_hdr */
ulint n_removed_logs) /*!< in: count of how many undo logs we
will cut off from the end of the
history list */
trx_rseg_t* rseg,
fil_addr_t hdr_addr)
{
mtr_t mtr;
trx_rsegf_t* rseg_hdr;
@@ -360,16 +375,7 @@ trx_purge_free_segment(
history list: otherwise, in case of a database crash, the segment
could become inaccessible garbage in the file space. */
flst_cut_end(rseg_hdr + TRX_RSEG_HISTORY,
log_hdr + TRX_UNDO_HISTORY_NODE, n_removed_logs, &mtr);
#ifdef HAVE_ATOMIC_BUILTINS
os_atomic_decrement_ulint(&trx_sys->rseg_history_len, n_removed_logs);
#else
mutex_enter(&trx_sys->mutex);
trx_sys->rseg_history_len -= n_removed_logs;
mutex_exit(&trx_sys->mutex);
#endif /* HAVE_ATOMIC_BUILTINS */
trx_purge_remove_log_hdr(rseg_hdr, log_hdr, &mtr);
do {
@@ -411,7 +417,6 @@ trx_purge_truncate_rseg_history(
page_t* undo_page;
trx_ulogf_t* log_hdr;
trx_usegf_t* seg_hdr;
ulint n_removed_logs = 0;
mtr_t mtr;
trx_id_t undo_trx_no;
@@ -449,19 +454,6 @@ loop:
hdr_addr.boffset, limit->undo_no);
}
#ifdef HAVE_ATOMIC_BUILTINS
os_atomic_decrement_ulint(
&trx_sys->rseg_history_len, n_removed_logs);
#else
mutex_enter(&trx_sys->mutex);
trx_sys->rseg_history_len -= n_removed_logs;
mutex_exit(&trx_sys->mutex);
#endif /* HAVE_ATOMIC_BUILTINS */
flst_truncate_end(rseg_hdr + TRX_RSEG_HISTORY,
log_hdr + TRX_UNDO_HISTORY_NODE,
n_removed_logs, &mtr);
mutex_exit(&(rseg->mutex));
mtr_commit(&mtr);
@@ -470,7 +462,6 @@ loop:
prev_hdr_addr = trx_purge_get_log_from_hist(
flst_get_prev_addr(log_hdr + TRX_UNDO_HISTORY_NODE, &mtr));
n_removed_logs++;
seg_hdr = undo_page + TRX_UNDO_SEG_HDR;
@@ -482,10 +473,14 @@ loop:
mutex_exit(&(rseg->mutex));
mtr_commit(&mtr);
trx_purge_free_segment(rseg, hdr_addr, n_removed_logs);
/* calls the trx_purge_remove_log_hdr()
inside trx_purge_free_segment(). */
trx_purge_free_segment(rseg, hdr_addr);
n_removed_logs = 0;
} else {
/* Remove the log hdr from the rseg history. */
trx_purge_remove_log_hdr(rseg_hdr, log_hdr, &mtr);
mutex_exit(&(rseg->mutex));
mtr_commit(&mtr);
}

View File

@@ -1572,7 +1572,7 @@ trx_commit_in_memory(
ut_ad(!trx->in_rw_trx_list);
#ifdef WITH_WSREP
if (wsrep_on(trx->mysql_thd)) {
if (trx->mysql_thd && wsrep_on(trx->mysql_thd)) {
trx->lock.was_chosen_as_deadlock_victim = FALSE;
}
#endif