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:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -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%';
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
--source include/not_valgrind.inc
|
||||
--disable_ps_protocol
|
||||
|
||||
SET GLOBAL net_write_timeout = 900;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
/*
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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(). */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user