MDEV-15528 Punch holes when pages are freed

The following parameters are deprecated:

  innodb-background-scrub-data-uncompressed
  innodb-background-scrub-data-compressed
  innodb-background-scrub-data-interval
  innodb-background-scrub-data-check-interval

Removed scrubbing code completely(btr0scrub.h, btr0scrub.cc)
Removed information_schema.innodb_tablespaces_scrubbing tables
Removed the scrubbing logic from fil_crypt_thread()
This commit is contained in:
Thirunarayanan Balathandayuthapani 2020-03-10 10:47:24 +05:30
parent a35b4ae898
commit a5584b13d1
26 changed files with 160 additions and 1823 deletions

View file

@ -39,7 +39,6 @@ INNODB_SYS_TABLES
INNODB_SYS_TABLESTATS
INNODB_SYS_VIRTUAL
INNODB_TABLESPACES_ENCRYPTION
INNODB_TABLESPACES_SCRUBBING
INNODB_TRX
KEY_CACHES
KEY_COLUMN_USAGE
@ -120,7 +119,6 @@ INNODB_SYS_TABLES TABLE_ID
INNODB_SYS_TABLESTATS TABLE_ID
INNODB_SYS_VIRTUAL TABLE_ID
INNODB_TABLESPACES_ENCRYPTION SPACE
INNODB_TABLESPACES_SCRUBBING SPACE
INNODB_TRX trx_id
KEY_CACHES KEY_CACHE_NAME
KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
@ -201,7 +199,6 @@ INNODB_SYS_TABLES TABLE_ID
INNODB_SYS_TABLESTATS TABLE_ID
INNODB_SYS_VIRTUAL TABLE_ID
INNODB_TABLESPACES_ENCRYPTION SPACE
INNODB_TABLESPACES_SCRUBBING SPACE
INNODB_TRX trx_id
KEY_CACHES KEY_CACHE_NAME
KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
@ -287,7 +284,6 @@ INNODB_SYS_TABLES information_schema.INNODB_SYS_TABLES 1
INNODB_SYS_TABLESTATS information_schema.INNODB_SYS_TABLESTATS 1
INNODB_SYS_VIRTUAL information_schema.INNODB_SYS_VIRTUAL 1
INNODB_TABLESPACES_ENCRYPTION information_schema.INNODB_TABLESPACES_ENCRYPTION 1
INNODB_TABLESPACES_SCRUBBING information_schema.INNODB_TABLESPACES_SCRUBBING 1
INNODB_TRX information_schema.INNODB_TRX 1
KEY_CACHES information_schema.KEY_CACHES 1
KEY_COLUMN_USAGE information_schema.KEY_COLUMN_USAGE 1
@ -358,7 +354,6 @@ Database: information_schema
| INNODB_SYS_TABLESTATS |
| INNODB_SYS_VIRTUAL |
| INNODB_TABLESPACES_ENCRYPTION |
| INNODB_TABLESPACES_SCRUBBING |
| INNODB_TRX |
| KEY_CACHES |
| KEY_COLUMN_USAGE |
@ -429,7 +424,6 @@ Database: INFORMATION_SCHEMA
| INNODB_SYS_TABLESTATS |
| INNODB_SYS_VIRTUAL |
| INNODB_TABLESPACES_ENCRYPTION |
| INNODB_TABLESPACES_SCRUBBING |
| INNODB_TRX |
| KEY_CACHES |
| KEY_COLUMN_USAGE |
@ -465,5 +459,5 @@ Wildcard: inf_rmation_schema
| information_schema |
SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') GROUP BY TABLE_SCHEMA;
table_schema count(*)
information_schema 66
information_schema 65
mysql 31

View file

@ -66,8 +66,6 @@ create sql security invoker view i_sys_virtual as select * from information_sche
create sql security definer view d_sys_virtual as select * from information_schema.innodb_sys_virtual;
create sql security invoker view i_tablespaces_encryption as select * from information_schema.innodb_tablespaces_encryption;
create sql security definer view d_tablespaces_encryption as select * from information_schema.innodb_tablespaces_encryption;
create sql security invoker view i_tablespaces_scrubbing as select * from information_schema.innodb_tablespaces_scrubbing;
create sql security definer view d_tablespaces_scrubbing as select * from information_schema.innodb_tablespaces_scrubbing;
create sql security invoker view i_trx as select * from information_schema.innodb_trx;
create sql security definer view d_trx as select * from information_schema.innodb_trx;
connection select_only;
@ -284,13 +282,6 @@ ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) fo
select count(*) > -1 from d_tablespaces_encryption;
count(*) > -1
1
select count(*) > -1 from information_schema.innodb_tablespaces_scrubbing;
ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
select count(*) > -1 from i_tablespaces_scrubbing;
ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
select count(*) > -1 from d_tablespaces_scrubbing;
count(*) > -1
1
select count(*) > -1 from information_schema.innodb_trx;
ERROR 42000: Access denied; you need (at least one of) the PROCESS privilege(s) for this operation
select count(*) > -1 from i_trx;

View file

@ -393,10 +393,6 @@ select * from information_schema.innodb_tablespaces_encryption;
SPACE NAME ENCRYPTION_SCHEME KEYSERVER_REQUESTS MIN_KEY_VERSION CURRENT_KEY_VERSION KEY_ROTATION_PAGE_NUMBER KEY_ROTATION_MAX_PAGE_NUMBER CURRENT_KEY_ID ROTATING_OR_FLUSHING
Warnings:
Warning 1012 InnoDB: SELECTing from INFORMATION_SCHEMA.innodb_tablespaces_encryption but the InnoDB storage engine is not installed
select * from information_schema.innodb_tablespaces_scrubbing;
SPACE NAME COMPRESSED LAST_SCRUB_COMPLETED CURRENT_SCRUB_STARTED CURRENT_SCRUB_ACTIVE_THREADS CURRENT_SCRUB_PAGE_NUMBER CURRENT_SCRUB_MAX_PAGE_NUMBER ON_SSD
Warnings:
Warning 1012 InnoDB: SELECTing from INFORMATION_SCHEMA.innodb_tablespaces_scrubbing but the InnoDB storage engine is not installed
select * from information_schema.innodb_mutexes;
NAME CREATE_FILE CREATE_LINE OS_WAITS
Warnings:

View file

@ -30,4 +30,3 @@
--enable-plugin-innodb-mutexes
--enable-plugin-innodb-sys-semaphore-waits
--enable-plugin-innodb-tablespaces-encryption
--enable-plugin-innodb-tablespaces-scrubbing

View file

@ -103,9 +103,6 @@ create sql security definer view d_sys_virtual as select * from information_sche
create sql security invoker view i_tablespaces_encryption as select * from information_schema.innodb_tablespaces_encryption;
create sql security definer view d_tablespaces_encryption as select * from information_schema.innodb_tablespaces_encryption;
create sql security invoker view i_tablespaces_scrubbing as select * from information_schema.innodb_tablespaces_scrubbing;
create sql security definer view d_tablespaces_scrubbing as select * from information_schema.innodb_tablespaces_scrubbing;
create sql security invoker view i_trx as select * from information_schema.innodb_trx;
create sql security definer view d_trx as select * from information_schema.innodb_trx;
@ -293,12 +290,6 @@ select count(*) > -1 from information_schema.innodb_tablespaces_encryption;
select count(*) > -1 from i_tablespaces_encryption;
select count(*) > -1 from d_tablespaces_encryption;
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
select count(*) > -1 from information_schema.innodb_tablespaces_scrubbing;
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
select count(*) > -1 from i_tablespaces_scrubbing;
select count(*) > -1 from d_tablespaces_scrubbing;
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
select count(*) > -1 from information_schema.innodb_trx;
--error ER_SPECIFIC_ACCESS_DENIED_ERROR

View file

@ -32,6 +32,5 @@ select * from information_schema.innodb_sys_datafiles;
--error 0,1109
select * from information_schema.innodb_changed_pages;
select * from information_schema.innodb_tablespaces_encryption;
select * from information_schema.innodb_tablespaces_scrubbing;
select * from information_schema.innodb_mutexes;
select * from information_schema.innodb_sys_semaphore_waits;

View file

@ -1 +0,0 @@
--innodb_tablespaces_scrubbing

View file

@ -1,13 +0,0 @@
SHOW CREATE TABLE INFORMATION_SCHEMA.INNODB_TABLESPACES_SCRUBBING;
Table Create Table
INNODB_TABLESPACES_SCRUBBING CREATE TEMPORARY TABLE `INNODB_TABLESPACES_SCRUBBING` (
`SPACE` bigint(21) unsigned NOT NULL DEFAULT 0,
`NAME` varchar(655) DEFAULT NULL,
`COMPRESSED` int(1) unsigned NOT NULL DEFAULT 0,
`LAST_SCRUB_COMPLETED` datetime DEFAULT NULL,
`CURRENT_SCRUB_STARTED` datetime DEFAULT NULL,
`CURRENT_SCRUB_ACTIVE_THREADS` int(11) unsigned DEFAULT NULL,
`CURRENT_SCRUB_PAGE_NUMBER` bigint(21) unsigned NOT NULL DEFAULT 0,
`CURRENT_SCRUB_MAX_PAGE_NUMBER` bigint(21) unsigned NOT NULL DEFAULT 0,
`ON_SSD` int(1) unsigned NOT NULL DEFAULT 0
) ENGINE=MEMORY DEFAULT CHARSET=utf8

View file

@ -1,3 +0,0 @@
--source include/have_innodb.inc
SHOW CREATE TABLE INFORMATION_SCHEMA.INNODB_TABLESPACES_SCRUBBING;

View file

@ -4,60 +4,74 @@ SET @start_global_value = @@global.innodb_background_scrub_data_check_interval;
#
select @@global.innodb_background_scrub_data_check_interval;
@@global.innodb_background_scrub_data_check_interval
3600
0
set global innodb_background_scrub_data_check_interval=10;
Warnings:
Warning 138 The parameter innodb_background_scrub_data_check_interval is deprecated and has no effect.
select @@global.innodb_background_scrub_data_check_interval;
@@global.innodb_background_scrub_data_check_interval
10
0
set global innodb_background_scrub_data_check_interval=DEFAULT;
Warnings:
Warning 138 The parameter innodb_background_scrub_data_check_interval is deprecated and has no effect.
select @@global.innodb_background_scrub_data_check_interval;
@@global.innodb_background_scrub_data_check_interval
3600
0
set global innodb_background_scrub_data_check_interval=20;
Warnings:
Warning 138 The parameter innodb_background_scrub_data_check_interval is deprecated and has no effect.
select @@global.innodb_background_scrub_data_check_interval;
@@global.innodb_background_scrub_data_check_interval
20
0
set global innodb_background_scrub_data_check_interval=DEFAULT;
Warnings:
Warning 138 The parameter innodb_background_scrub_data_check_interval is deprecated and has no effect.
select @@global.innodb_background_scrub_data_check_interval;
@@global.innodb_background_scrub_data_check_interval
3600
0
#
# exists as global only
#
select @@global.innodb_background_scrub_data_check_interval;
@@global.innodb_background_scrub_data_check_interval
3600
0
select @@session.innodb_background_scrub_data_check_interval;
ERROR HY000: Variable 'innodb_background_scrub_data_check_interval' is a GLOBAL variable
show global variables like 'innodb_background_scrub_data_check_interval';
Variable_name Value
innodb_background_scrub_data_check_interval 3600
innodb_background_scrub_data_check_interval 0
show session variables like 'innodb_background_scrub_data_check_interval';
Variable_name Value
innodb_background_scrub_data_check_interval 3600
innodb_background_scrub_data_check_interval 0
select * from information_schema.global_variables
where variable_name='innodb_background_scrub_data_check_interval';
VARIABLE_NAME VARIABLE_VALUE
INNODB_BACKGROUND_SCRUB_DATA_CHECK_INTERVAL 3600
INNODB_BACKGROUND_SCRUB_DATA_CHECK_INTERVAL 0
select * from information_schema.session_variables
where variable_name='innodb_background_scrub_data_check_interval';
VARIABLE_NAME VARIABLE_VALUE
INNODB_BACKGROUND_SCRUB_DATA_CHECK_INTERVAL 3600
INNODB_BACKGROUND_SCRUB_DATA_CHECK_INTERVAL 0
#
# show that it's writable
#
set global innodb_background_scrub_data_check_interval=10;
Warnings:
Warning 138 The parameter innodb_background_scrub_data_check_interval is deprecated and has no effect.
select @@global.innodb_background_scrub_data_check_interval;
@@global.innodb_background_scrub_data_check_interval
10
0
set global innodb_background_scrub_data_check_interval=20;
Warnings:
Warning 138 The parameter innodb_background_scrub_data_check_interval is deprecated and has no effect.
select @@global.innodb_background_scrub_data_check_interval;
@@global.innodb_background_scrub_data_check_interval
20
0
set global innodb_background_scrub_data_check_interval=1;
Warnings:
Warning 138 The parameter innodb_background_scrub_data_check_interval is deprecated and has no effect.
select @@global.innodb_background_scrub_data_check_interval;
@@global.innodb_background_scrub_data_check_interval
1
0
set session innodb_background_scrub_data_check_interval=1;
ERROR HY000: Variable 'innodb_background_scrub_data_check_interval' is a GLOBAL variable and should be set with SET GLOBAL
#
@ -70,3 +84,5 @@ ERROR 42000: Incorrect argument type to variable 'innodb_background_scrub_data_c
set global innodb_background_scrub_data_check_interval="foo";
ERROR 42000: Incorrect argument type to variable 'innodb_background_scrub_data_check_interval'
SET @@global.innodb_background_scrub_data_check_interval = @start_global_value;
Warnings:
Warning 138 The parameter innodb_background_scrub_data_check_interval is deprecated and has no effect.

View file

@ -25,17 +25,23 @@ INNODB_BACKGROUND_SCRUB_DATA_COMPRESSED OFF
# show that it's writable
#
set global innodb_background_scrub_data_compressed=ON;
Warnings:
Warning 138 The parameter innodb_background_scrub_data_compressed is deprecated and has no effect.
select @@global.innodb_background_scrub_data_compressed;
@@global.innodb_background_scrub_data_compressed
1
0
set global innodb_background_scrub_data_compressed=OFF;
Warnings:
Warning 138 The parameter innodb_background_scrub_data_compressed is deprecated and has no effect.
select @@global.innodb_background_scrub_data_compressed;
@@global.innodb_background_scrub_data_compressed
0
set global innodb_background_scrub_data_compressed=1;
Warnings:
Warning 138 The parameter innodb_background_scrub_data_compressed is deprecated and has no effect.
select @@global.innodb_background_scrub_data_compressed;
@@global.innodb_background_scrub_data_compressed
1
0
set session innodb_background_scrub_data_compressed=1;
ERROR HY000: Variable 'innodb_background_scrub_data_compressed' is a GLOBAL variable and should be set with SET GLOBAL
#
@ -48,3 +54,5 @@ ERROR 42000: Incorrect argument type to variable 'innodb_background_scrub_data_c
set global innodb_background_scrub_data_compressed="foo";
ERROR 42000: Variable 'innodb_background_scrub_data_compressed' can't be set to the value of 'foo'
SET @@global.innodb_background_scrub_data_compressed = @start_global_value;
Warnings:
Warning 138 The parameter innodb_background_scrub_data_compressed is deprecated and has no effect.

View file

@ -4,38 +4,44 @@ SET @start_global_value = @@global.innodb_background_scrub_data_interval;
#
select @@global.innodb_background_scrub_data_interval;
@@global.innodb_background_scrub_data_interval
604800
0
select @@session.innodb_background_scrub_data_interval;
ERROR HY000: Variable 'innodb_background_scrub_data_interval' is a GLOBAL variable
show global variables like 'innodb_background_scrub_data_interval';
Variable_name Value
innodb_background_scrub_data_interval 604800
innodb_background_scrub_data_interval 0
show session variables like 'innodb_background_scrub_data_interval';
Variable_name Value
innodb_background_scrub_data_interval 604800
innodb_background_scrub_data_interval 0
select * from information_schema.global_variables
where variable_name='innodb_background_scrub_data_interval';
VARIABLE_NAME VARIABLE_VALUE
INNODB_BACKGROUND_SCRUB_DATA_INTERVAL 604800
INNODB_BACKGROUND_SCRUB_DATA_INTERVAL 0
select * from information_schema.session_variables
where variable_name='innodb_background_scrub_data_interval';
VARIABLE_NAME VARIABLE_VALUE
INNODB_BACKGROUND_SCRUB_DATA_INTERVAL 604800
INNODB_BACKGROUND_SCRUB_DATA_INTERVAL 0
#
# show that it's writable
#
set global innodb_background_scrub_data_interval=100;
Warnings:
Warning 138 The parameter innodb_background_scrub_data_interval is deprecated and has no effect.
select @@global.innodb_background_scrub_data_interval;
@@global.innodb_background_scrub_data_interval
100
0
set global innodb_background_scrub_data_interval=200;
Warnings:
Warning 138 The parameter innodb_background_scrub_data_interval is deprecated and has no effect.
select @@global.innodb_background_scrub_data_interval;
@@global.innodb_background_scrub_data_interval
200
0
set global innodb_background_scrub_data_interval=300;
Warnings:
Warning 138 The parameter innodb_background_scrub_data_interval is deprecated and has no effect.
select @@global.innodb_background_scrub_data_interval;
@@global.innodb_background_scrub_data_interval
300
0
set session innodb_background_scrub_data_interval=400;
ERROR HY000: Variable 'innodb_background_scrub_data_interval' is a GLOBAL variable and should be set with SET GLOBAL
#
@ -48,3 +54,5 @@ ERROR 42000: Incorrect argument type to variable 'innodb_background_scrub_data_i
set global innodb_background_scrub_data_interval="foo";
ERROR 42000: Incorrect argument type to variable 'innodb_background_scrub_data_interval'
SET @@global.innodb_background_scrub_data_interval = @start_global_value;
Warnings:
Warning 138 The parameter innodb_background_scrub_data_interval is deprecated and has no effect.

View file

@ -25,17 +25,23 @@ INNODB_BACKGROUND_SCRUB_DATA_UNCOMPRESSED OFF
# show that it's writable
#
set global innodb_background_scrub_data_uncompressed=ON;
Warnings:
Warning 138 The parameter innodb_background_scrub_data_uncompressed is deprecated and has no effect.
select @@global.innodb_background_scrub_data_uncompressed;
@@global.innodb_background_scrub_data_uncompressed
1
0
set global innodb_background_scrub_data_uncompressed=OFF;
Warnings:
Warning 138 The parameter innodb_background_scrub_data_uncompressed is deprecated and has no effect.
select @@global.innodb_background_scrub_data_uncompressed;
@@global.innodb_background_scrub_data_uncompressed
0
set global innodb_background_scrub_data_uncompressed=1;
Warnings:
Warning 138 The parameter innodb_background_scrub_data_uncompressed is deprecated and has no effect.
select @@global.innodb_background_scrub_data_uncompressed;
@@global.innodb_background_scrub_data_uncompressed
1
0
set session innodb_background_scrub_data_uncompressed=1;
ERROR HY000: Variable 'innodb_background_scrub_data_uncompressed' is a GLOBAL variable and should be set with SET GLOBAL
#
@ -48,3 +54,5 @@ ERROR 42000: Incorrect argument type to variable 'innodb_background_scrub_data_u
set global innodb_background_scrub_data_uncompressed="foo";
ERROR 42000: Variable 'innodb_background_scrub_data_uncompressed' can't be set to the value of 'foo'
SET @@global.innodb_background_scrub_data_uncompressed = @start_global_value;
Warnings:
Warning 138 The parameter innodb_background_scrub_data_uncompressed is deprecated and has no effect.

View file

@ -1,50 +0,0 @@
SET @start_global_value = @@global.innodb_debug_force_scrubbing;
#
# exists as global only
#
select @@global.innodb_debug_force_scrubbing;
@@global.innodb_debug_force_scrubbing
0
select @@session.innodb_debug_force_scrubbing;
ERROR HY000: Variable 'innodb_debug_force_scrubbing' is a GLOBAL variable
show global variables like 'innodb_debug_force_scrubbing';
Variable_name Value
innodb_debug_force_scrubbing OFF
show session variables like 'innodb_debug_force_scrubbing';
Variable_name Value
innodb_debug_force_scrubbing OFF
select * from information_schema.global_variables
where variable_name='innodb_debug_force_scrubbing';
VARIABLE_NAME VARIABLE_VALUE
INNODB_DEBUG_FORCE_SCRUBBING OFF
select * from information_schema.session_variables
where variable_name='innodb_debug_force_scrubbing';
VARIABLE_NAME VARIABLE_VALUE
INNODB_DEBUG_FORCE_SCRUBBING OFF
#
# show that it's writable
#
set global innodb_debug_force_scrubbing=ON;
select @@global.innodb_debug_force_scrubbing;
@@global.innodb_debug_force_scrubbing
1
set global innodb_debug_force_scrubbing=OFF;
select @@global.innodb_debug_force_scrubbing;
@@global.innodb_debug_force_scrubbing
0
set global innodb_debug_force_scrubbing=1;
select @@global.innodb_debug_force_scrubbing;
@@global.innodb_debug_force_scrubbing
1
set session innodb_debug_force_scrubbing=1;
ERROR HY000: Variable 'innodb_debug_force_scrubbing' is a GLOBAL variable and should be set with SET GLOBAL
#
# incorrect types
#
set global innodb_debug_force_scrubbing=1.1;
ERROR 42000: Incorrect argument type to variable 'innodb_debug_force_scrubbing'
set global innodb_debug_force_scrubbing=1e1;
ERROR 42000: Incorrect argument type to variable 'innodb_debug_force_scrubbing'
set global innodb_debug_force_scrubbing="foo";
ERROR 42000: Variable 'innodb_debug_force_scrubbing' can't be set to the value of 'foo'
SET @@global.innodb_debug_force_scrubbing = @start_global_value;

View file

@ -107,12 +107,12 @@ READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME INNODB_BACKGROUND_SCRUB_DATA_CHECK_INTERVAL
SESSION_VALUE NULL
DEFAULT_VALUE 3600
DEFAULT_VALUE 0
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT check if spaces needs scrubbing every innodb_background_scrub_data_check_interval seconds
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 4294967295
VARIABLE_COMMENT Deprecated parameter with no effect.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 0
NUMERIC_BLOCK_SIZE 0
ENUM_VALUE_LIST NULL
READ_ONLY NO
@ -122,21 +122,21 @@ SESSION_VALUE NULL
DEFAULT_VALUE OFF
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BOOLEAN
VARIABLE_COMMENT Enable scrubbing of compressed data by background threads (same as encryption_threads)
VARIABLE_COMMENT Deprecated parameter with no effect.
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,ON
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME INNODB_BACKGROUND_SCRUB_DATA_INTERVAL
SESSION_VALUE NULL
DEFAULT_VALUE 604800
DEFAULT_VALUE 0
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT scrub spaces that were last scrubbed longer than innodb_background_scrub_data_interval seconds ago
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 4294967295
VARIABLE_COMMENT Deprecated parameter with no effect.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 0
NUMERIC_BLOCK_SIZE 0
ENUM_VALUE_LIST NULL
READ_ONLY NO
@ -146,13 +146,13 @@ SESSION_VALUE NULL
DEFAULT_VALUE OFF
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BOOLEAN
VARIABLE_COMMENT Enable scrubbing of uncompressed data by background threads (same as encryption_threads)
VARIABLE_COMMENT Deprecated parameter with no effect.
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,ON
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME INNODB_BUFFER_POOL_CHUNK_SIZE
SESSION_VALUE NULL
DEFAULT_VALUE 134217728
@ -513,18 +513,6 @@ NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,ON
READ_ONLY NO
COMMAND_LINE_ARGUMENT NONE
VARIABLE_NAME INNODB_DEBUG_FORCE_SCRUBBING
SESSION_VALUE NULL
DEFAULT_VALUE OFF
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BOOLEAN
VARIABLE_COMMENT Perform extra scrubbing to increase test exposure
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,ON
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME INNODB_DEFAULT_ENCRYPTION_KEY_ID
SESSION_VALUE 1
DEFAULT_VALUE 1
@ -710,7 +698,7 @@ SESSION_VALUE NULL
DEFAULT_VALUE 0
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT Number of threads performing background key rotation and scrubbing
VARIABLE_COMMENT Number of threads performing background key rotation
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 4294967295
NUMERIC_BLOCK_SIZE 0

View file

@ -1,42 +0,0 @@
# bool global
--source include/have_innodb.inc
--source include/have_debug.inc
SET @start_global_value = @@global.innodb_debug_force_scrubbing;
--echo #
--echo # exists as global only
--echo #
select @@global.innodb_debug_force_scrubbing;
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
select @@session.innodb_debug_force_scrubbing;
show global variables like 'innodb_debug_force_scrubbing';
show session variables like 'innodb_debug_force_scrubbing';
select * from information_schema.global_variables
where variable_name='innodb_debug_force_scrubbing';
select * from information_schema.session_variables
where variable_name='innodb_debug_force_scrubbing';
--echo #
--echo # show that it's writable
--echo #
set global innodb_debug_force_scrubbing=ON;
select @@global.innodb_debug_force_scrubbing;
set global innodb_debug_force_scrubbing=OFF;
select @@global.innodb_debug_force_scrubbing;
set global innodb_debug_force_scrubbing=1;
select @@global.innodb_debug_force_scrubbing;
--error ER_GLOBAL_VARIABLE
set session innodb_debug_force_scrubbing=1;
--echo #
--echo # incorrect types
--echo #
--error ER_WRONG_TYPE_FOR_VAR
set global innodb_debug_force_scrubbing=1.1;
--error ER_WRONG_TYPE_FOR_VAR
set global innodb_debug_force_scrubbing=1e1;
--error ER_WRONG_VALUE_FOR_VAR
set global innodb_debug_force_scrubbing="foo";
SET @@global.innodb_debug_force_scrubbing = @start_global_value;

View file

@ -26,7 +26,6 @@ SET(INNOBASE_SOURCES
btr/btr0bulk.cc
btr/btr0cur.cc
btr/btr0pcur.cc
btr/btr0scrub.cc
btr/btr0sea.cc
btr/btr0defragment.cc
buf/buf0buddy.cc

View file

@ -1,909 +0,0 @@
// Copyright (c) 2014, Google Inc.
// Copyright (c) 2017, 2020, MariaDB Corporation.
/**************************************************//**
@file btr/btr0scrub.cc
Scrubbing of btree pages
*******************************************************/
#include "btr0btr.h"
#include "btr0cur.h"
#include "btr0scrub.h"
#include "ibuf0ibuf.h"
#include "fsp0fsp.h"
#include "dict0dict.h"
#include "mtr0mtr.h"
/* used when trying to acquire dict-lock */
UNIV_INTERN bool fil_crypt_is_closing(ulint space);
/**
* scrub data at delete time (e.g purge thread)
*/
my_bool srv_immediate_scrub_data_uncompressed = false;
/**
* background scrub uncompressed data
*
* if srv_immediate_scrub_data_uncompressed is enabled
* this is only needed to handle "old" data
*/
my_bool srv_background_scrub_data_uncompressed = false;
/**
* backgrounds scrub compressed data
*
* reorganize compressed page for scrubbing
* (only way to scrub compressed data)
*/
my_bool srv_background_scrub_data_compressed = false;
/* check spaces once per hour */
UNIV_INTERN uint srv_background_scrub_data_check_interval = (60 * 60);
/* default to scrub spaces that hasn't been scrubbed in a week */
UNIV_INTERN uint srv_background_scrub_data_interval = (7 * 24 * 60 * 60);
/**
* statistics for scrubbing by background threads
*/
static btr_scrub_stat_t scrub_stat;
static ib_mutex_t scrub_stat_mutex;
#ifdef UNIV_PFS_MUTEX
UNIV_INTERN mysql_pfs_key_t scrub_stat_mutex_key;
#endif
#ifdef UNIV_DEBUG
/**
* srv_scrub_force_testing
*
* - force scrubbing using background threads even for uncompressed tables
* - force pessimistic scrubbing (page split) even if not needed
* (see test_pessimistic_scrub_pct)
*/
my_bool srv_scrub_force_testing = true;
/**
* Force pessimistic scrubbing in 50% of the cases (UNIV_DEBUG only)
*/
static int test_pessimistic_scrub_pct = 50;
#endif
static uint scrub_compression_level = page_zip_level;
/**************************************************************//**
Log a scrubbing failure */
static
void
log_scrub_failure(
/*===============*/
dict_index_t* index, /*!< in: index */
btr_scrub_t* scrub_data, /*!< in: data to store statistics on */
buf_block_t* block, /*!< in: block */
dberr_t err) /*!< in: error */
{
const char* reason = "unknown";
switch(err) {
case DB_UNDERFLOW:
reason = "too few records on page";
scrub_data->scrub_stat.page_split_failures_underflow++;
break;
case DB_INDEX_CORRUPT:
reason = "unable to find index!";
scrub_data->scrub_stat.page_split_failures_missing_index++;
break;
case DB_OUT_OF_FILE_SPACE:
reason = "out of filespace";
scrub_data->scrub_stat.page_split_failures_out_of_filespace++;
break;
default:
ut_ad(0);
reason = "unknown";
scrub_data->scrub_stat.page_split_failures_unknown++;
}
ib::warn() << "Failed to scrub index " << index->name
<< " of table " << index->table->name
<< " page " << block->page.id << ": " << reason;
}
/****************************************************************
Lock dict mutexes */
static
bool
btr_scrub_lock_dict_func(ulint space_id, bool lock_to_close_table,
const char * file, uint line)
{
time_t start = time(0);
time_t last = start;
/* FIXME: this is not the proper way of doing things. The
dict_sys.mutex should not be held by any thread for longer
than a few microseconds. It must not be held during I/O,
for example. So, what is the purpose for this busy-waiting?
This function should be rewritten as part of MDEV-8139:
Fix scrubbing tests. */
while (mutex_enter_nowait(&dict_sys.mutex)) {
/* if we lock to close a table, we wait forever
* if we don't lock to close a table, we check if space
* is closing, and then instead give up
*/
if (lock_to_close_table) {
} else if (fil_space_t* space = fil_space_acquire(space_id)) {
bool stopping = space->is_stopping();
space->release();
if (stopping) {
return false;
}
} else {
return false;
}
os_thread_sleep(250000);
time_t now = time(0);
if (now >= last + 30) {
fprintf(stderr,
"WARNING: %s:%u waited %ld seconds for"
" dict_sys lock, space: " ULINTPF
" lock_to_close_table: %d\n",
file, line, long(now - start), space_id,
lock_to_close_table);
last = now;
}
}
ut_ad(mutex_own(&dict_sys.mutex));
return true;
}
#define btr_scrub_lock_dict(space, lock_to_close_table) \
btr_scrub_lock_dict_func(space, lock_to_close_table, __FILE__, __LINE__)
/****************************************************************
Unlock dict mutexes */
static
void
btr_scrub_unlock_dict()
{
dict_mutex_exit_for_mysql();
}
/****************************************************************
Release reference to table
*/
static
void
btr_scrub_table_close(
/*==================*/
dict_table_t* table) /*!< in: table */
{
bool dict_locked = true;
bool try_drop = false;
table->stats_bg_flag &= ~BG_SCRUB_IN_PROGRESS;
dict_table_close(table, dict_locked, try_drop);
}
/****************************************************************
Release reference to table
*/
static
void
btr_scrub_table_close_for_thread(
btr_scrub_t *scrub_data)
{
if (scrub_data->current_table == NULL) {
return;
}
if (fil_space_t* space = fil_space_acquire(scrub_data->space)) {
/* If tablespace is not marked as stopping perform
the actual close. */
if (!space->is_stopping()) {
mutex_enter(&dict_sys.mutex);
/* perform the actual closing */
btr_scrub_table_close(scrub_data->current_table);
mutex_exit(&dict_sys.mutex);
}
space->release();
}
scrub_data->current_table = NULL;
scrub_data->current_index = NULL;
}
/**************************************************************//**
Check if scrubbing is turned ON or OFF */
static
bool
check_scrub_setting(
/*=====================*/
btr_scrub_t* scrub_data) /*!< in: scrub data */
{
if (scrub_data->compressed)
return srv_background_scrub_data_compressed;
else
return srv_background_scrub_data_uncompressed;
}
#define IBUF_INDEX_ID (DICT_IBUF_ID_MIN + IBUF_SPACE_ID)
/**************************************************************//**
Check if a page needs scrubbing */
UNIV_INTERN
int
btr_page_needs_scrubbing(
/*=====================*/
btr_scrub_t* scrub_data, /*!< in: scrub data */
buf_block_t* block, /*!< in: block to check, latched */
btr_scrub_page_allocation_status_t allocated) /*!< in: is block known
to be allocated */
{
/**
* Check if scrubbing has been turned OFF.
*
* at start of space, we check if scrubbing is ON or OFF
* here we only check if scrubbing is turned OFF.
*
* Motivation is that it's only valueable to have a full table (space)
* scrubbed.
*/
if (!check_scrub_setting(scrub_data)) {
bool before_value = scrub_data->scrubbing;
scrub_data->scrubbing = false;
if (before_value == true) {
/* we toggle scrubbing from on to off */
return BTR_SCRUB_TURNED_OFF;
}
}
if (scrub_data->scrubbing == false) {
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
}
const page_t* page = buf_block_get_frame(block);
if (allocated == BTR_SCRUB_PAGE_ALLOCATED) {
if (fil_page_get_type(page) != FIL_PAGE_INDEX) {
/* this function is called from fil-crypt-threads.
* these threads iterate all pages of all tablespaces
* and don't know about fil_page_type.
* But scrubbing is only needed for index-pages. */
/**
* NOTE: scrubbing is also needed for UNDO pages,
* but they are scrubbed at purge-time, since they are
* uncompressed
*/
/* if encountering page type not needing scrubbing
release reference to table object */
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
}
if (!page_has_garbage(page)) {
/* no garbage (from deleted/shrunken records) */
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
}
} else if (allocated == BTR_SCRUB_PAGE_FREE ||
allocated == BTR_SCRUB_PAGE_ALLOCATION_UNKNOWN) {
switch (fil_page_get_type(page)) {
case FIL_PAGE_INDEX:
case FIL_PAGE_TYPE_ZBLOB:
case FIL_PAGE_TYPE_ZBLOB2:
break;
default:
/**
* If this is a dropped page, we also need to scrub
* BLOB pages
*/
/* if encountering page type not needing scrubbing
release reference to table object */
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
}
}
if (block->page.id.space() == TRX_SYS_SPACE
&& btr_page_get_index_id(page) == IBUF_INDEX_ID) {
/* skip ibuf */
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
}
return BTR_SCRUB_PAGE;
}
/****************************************************************
Handle a skipped page
*/
UNIV_INTERN
void
btr_scrub_skip_page(
/*==================*/
btr_scrub_t* scrub_data, /*!< in: data with scrub state */
int needs_scrubbing) /*!< in: return code from
btr_page_needs_scrubbing */
{
switch(needs_scrubbing) {
case BTR_SCRUB_SKIP_PAGE:
/* nothing todo */
return;
case BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE:
btr_scrub_table_close_for_thread(scrub_data);
return;
case BTR_SCRUB_TURNED_OFF:
case BTR_SCRUB_SKIP_PAGE_AND_COMPLETE_SPACE:
btr_scrub_complete_space(scrub_data);
return;
}
/* unknown value. should not happen */
ut_a(0);
}
/****************************************************************
Try to scrub a page.
return DB_SUCCESS on success or DB_OVERFLOW on failure */
static
dberr_t
btr_optimistic_scrub(
/*==================*/
btr_scrub_t* scrub_data, /*!< in: data with scrub state */
buf_block_t* block, /*!< in: block to scrub */
dict_index_t* index, /*!< in: index */
mtr_t* mtr) /*!< in: mtr */
{
#ifdef UNIV_DEBUG
if (srv_scrub_force_testing &&
page_get_n_recs(buf_block_get_frame(block)) > 2 &&
(rand() % 100) < test_pessimistic_scrub_pct) {
log_scrub_failure(index, scrub_data, block, DB_OVERFLOW);
return DB_OVERFLOW;
}
#endif
if (!btr_page_reorganize_block(scrub_compression_level, block,
index, mtr)) {
return DB_OVERFLOW;
}
/* We play safe and reset the free bits */
if (!dict_index_is_clust(index) &&
block != NULL) {
buf_frame_t* frame = buf_block_get_frame(block);
if (frame &&
page_is_leaf(frame)) {
ibuf_reset_free_bits(block);
}
}
scrub_data->scrub_stat.page_reorganizations++;
return DB_SUCCESS;
}
/****************************************************************
Try to scrub a page by splitting it
return DB_SUCCESS on success
DB_UNDERFLOW if page has too few records
DB_OUT_OF_FILE_SPACE if we can't find space for split */
static
dberr_t
btr_pessimistic_scrub(
/*==================*/
btr_scrub_t* scrub_data, /*!< in: data with scrub state */
buf_block_t* block, /*!< in: block to scrub */
dict_index_t* index, /*!< in: index */
mtr_t* mtr) /*!< in: mtr */
{
page_t* page = buf_block_get_frame(block);
if (page_get_n_recs(page) < 2) {
/**
* There is no way we can split a page with < 2 records
*/
log_scrub_failure(index, scrub_data, block, DB_UNDERFLOW);
return DB_UNDERFLOW;
}
/**
* Splitting page needs new space, allocate it here
* so that splitting won't fail due to this */
ulint n_extents = 3;
ulint n_reserved = 0;
if (!fsp_reserve_free_extents(&n_reserved, index->table->space,
n_extents, FSP_NORMAL, mtr)) {
log_scrub_failure(index, scrub_data, block,
DB_OUT_OF_FILE_SPACE);
return DB_OUT_OF_FILE_SPACE;
}
/* read block variables */
const uint32_t page_no = block->page.id.page_no();
const uint32_t left_page_no = btr_page_get_prev(page);
const uint32_t right_page_no = btr_page_get_next(page);
/**
* When splitting page, we need X-latches on left/right brothers
* see e.g btr_cur_latch_leaves
*/
if (left_page_no != FIL_NULL) {
/**
* pages needs to be locked left-to-right, release block
* and re-lock. We still have x-lock on index
* so this should be safe
*/
mtr->release_block_at_savepoint(scrub_data->savepoint, block);
btr_block_get(*index, left_page_no, RW_X_LATCH,
page_is_leaf(page), mtr);
/**
* Refetch block and re-initialize page
*/
block = btr_block_get(*index, page_no, RW_X_LATCH,
page_is_leaf(page), mtr);
page = buf_block_get_frame(block);
/**
* structure should be unchanged
*/
ut_a(left_page_no == btr_page_get_prev(page));
ut_a(right_page_no == btr_page_get_next(page));
}
if (right_page_no != FIL_NULL) {
btr_block_get(*index, right_page_no, RW_X_LATCH,
page_is_leaf(page), mtr);
}
/* arguments to btr_page_split_and_insert */
mem_heap_t* heap = NULL;
dtuple_t* entry = NULL;
offset_t* offsets = NULL;
ulint n_ext = 0;
ulint flags = BTR_MODIFY_TREE;
/**
* position a cursor on first record on page
*/
rec_t* rec = page_rec_get_next(page_get_infimum_rec(page));
btr_cur_t cursor;
btr_cur_position(index, rec, block, &cursor);
/**
* call split page with NULL as argument for entry to insert
*/
if (dict_index_get_page(index) == page_no) {
/* The page is the root page
* NOTE: ibuf_reset_free_bits is called inside
* btr_root_raise_and_insert */
rec = btr_root_raise_and_insert(
flags, &cursor, &offsets, &heap, entry, n_ext, mtr);
} else {
/* We play safe and reset the free bits
* NOTE: need to call this prior to btr_page_split_and_insert */
if (!dict_index_is_clust(index) &&
block != NULL) {
buf_frame_t* frame = buf_block_get_frame(block);
if (frame &&
page_is_leaf(frame)) {
ibuf_reset_free_bits(block);
}
}
rec = btr_page_split_and_insert(
flags, &cursor, &offsets, &heap, entry, n_ext, mtr);
}
if (heap) {
mem_heap_free(heap);
}
index->table->space->release_free_extents(n_reserved);
scrub_data->scrub_stat.page_splits++;
return DB_SUCCESS;
}
/****************************************************************
Location index by id for a table
return index or NULL */
static
dict_index_t*
find_index(
/*========*/
dict_table_t* table, /*!< in: table */
index_id_t index_id) /*!< in: index id */
{
if (table != NULL) {
dict_index_t* index = dict_table_get_first_index(table);
while (index != NULL) {
if (index->id == index_id)
return index;
index = dict_table_get_next_index(index);
}
}
return NULL;
}
/****************************************************************
Check if table should be scrubbed
*/
static
bool
btr_scrub_table_needs_scrubbing(
/*============================*/
dict_table_t* table) /*!< in: table */
{
if (table == NULL)
return false;
if (table->stats_bg_flag & BG_STAT_SHOULD_QUIT) {
return false;
}
if (table->to_be_dropped) {
return false;
}
if (!table->is_readable()) {
return false;
}
return true;
}
/****************************************************************
Check if index should be scrubbed
*/
static
bool
btr_scrub_index_needs_scrubbing(
/*============================*/
dict_index_t* index) /*!< in: index */
{
if (index == NULL)
return false;
if (dict_index_is_ibuf(index)) {
return false;
}
if (dict_index_is_online_ddl(index)) {
return false;
}
return true;
}
/****************************************************************
Get table and index and store it on scrub_data
*/
static
void
btr_scrub_get_table_and_index(
/*=========================*/
btr_scrub_t* scrub_data, /*!< in/out: scrub data */
index_id_t index_id) /*!< in: index id */
{
/* first check if it's an index to current table */
scrub_data->current_index = find_index(scrub_data->current_table,
index_id);
if (scrub_data->current_index != NULL) {
/* yes it was */
return;
}
if (!btr_scrub_lock_dict(scrub_data->space, false)) {
btr_scrub_complete_space(scrub_data);
return;
}
/* close current table (if any) */
if (scrub_data->current_table != NULL) {
btr_scrub_table_close(scrub_data->current_table);
scrub_data->current_table = NULL;
}
/* open table based on index_id */
dict_table_t* table = dict_table_open_on_index_id(index_id);
if (table != NULL) {
/* mark table as being scrubbed */
table->stats_bg_flag |= BG_SCRUB_IN_PROGRESS;
if (!btr_scrub_table_needs_scrubbing(table)) {
btr_scrub_table_close(table);
btr_scrub_unlock_dict();
return;
}
}
btr_scrub_unlock_dict();
scrub_data->current_table = table;
scrub_data->current_index = find_index(table, index_id);
}
/****************************************************************
Handle free page */
UNIV_INTERN
int
btr_scrub_free_page(
/*====================*/
btr_scrub_t* scrub_data, /*!< in/out: scrub data */
buf_block_t* block, /*!< in: block to scrub */
mtr_t* mtr) /*!< in: mtr */
{
// TODO(jonaso): scrub only what is actually needed
{
/* note: perform both the memset and setting of FIL_PAGE_TYPE
* wo/ logging. so that if we crash before page is flushed
* it will be found by scrubbing thread again
*/
memset(buf_block_get_frame(block) + PAGE_HEADER, 0,
srv_page_size - PAGE_HEADER);
mach_write_to_2(buf_block_get_frame(block) + FIL_PAGE_TYPE,
FIL_PAGE_TYPE_ALLOCATED);
}
page_create(block, mtr,
dict_table_is_comp(scrub_data->current_table));
mtr_commit(mtr);
/* page doesn't need further processing => SKIP
* and close table/index so that we don't keep references too long */
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
}
/****************************************************************
Recheck if a page needs scrubbing, and if it does load appropriate
table and index */
UNIV_INTERN
int
btr_scrub_recheck_page(
/*====================*/
btr_scrub_t* scrub_data, /*!< inut: scrub data */
buf_block_t* block, /*!< in: block */
btr_scrub_page_allocation_status_t allocated, /*!< in: is block
allocated or free */
mtr_t* mtr) /*!< in: mtr */
{
/* recheck if page needs scrubbing (knowing allocation status) */
int needs_scrubbing = btr_page_needs_scrubbing(
scrub_data, block, allocated);
if (needs_scrubbing != BTR_SCRUB_PAGE) {
mtr_commit(mtr);
return needs_scrubbing;
}
if (allocated == BTR_SCRUB_PAGE_FREE) {
/** we don't need to load table/index for free pages
* so scrub directly here */
/* mtr is committed inside btr_scrub_page_free */
return btr_scrub_free_page(scrub_data,
block,
mtr);
}
page_t* page = buf_block_get_frame(block);
index_id_t index_id = btr_page_get_index_id(page);
if (scrub_data->current_index == NULL ||
scrub_data->current_index->id != index_id) {
/**
* commit mtr (i.e release locks on block)
* and try to get table&index potentially loading it
* from disk
*/
mtr_commit(mtr);
btr_scrub_get_table_and_index(scrub_data, index_id);
} else {
/* we already have correct index
* commit mtr so that we can lock index before fetching page
*/
mtr_commit(mtr);
}
/* check if table is about to be dropped */
if (!btr_scrub_table_needs_scrubbing(scrub_data->current_table)) {
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
}
/* check if index is scrubbable */
if (!btr_scrub_index_needs_scrubbing(scrub_data->current_index)) {
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
}
mtr_start(mtr);
mtr_x_lock_index(scrub_data->current_index, mtr);
/** set savepoint for X-latch of block */
scrub_data->savepoint = mtr_set_savepoint(mtr);
return BTR_SCRUB_PAGE;
}
/****************************************************************
Perform actual scrubbing of page */
UNIV_INTERN
int
btr_scrub_page(
/*============*/
btr_scrub_t* scrub_data, /*!< in/out: scrub data */
buf_block_t* block, /*!< in: block */
btr_scrub_page_allocation_status_t allocated, /*!< in: is block
allocated or free */
mtr_t* mtr) /*!< in: mtr */
{
/* recheck if page needs scrubbing (knowing allocation status) */
int needs_scrubbing = BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
if (block) {
btr_page_needs_scrubbing(scrub_data, block, allocated);
}
if (!block || needs_scrubbing != BTR_SCRUB_PAGE) {
mtr_commit(mtr);
return needs_scrubbing;
}
if (allocated == BTR_SCRUB_PAGE_FREE) {
/* mtr is committed inside btr_scrub_page_free */
return btr_scrub_free_page(scrub_data,
block,
mtr);
}
/* check that table/index still match now that they are loaded */
if (!scrub_data->current_table->space
|| scrub_data->current_table->space_id != scrub_data->space) {
/* this is truncate table */
mtr_commit(mtr);
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
}
if (scrub_data->current_index->table != scrub_data->current_table) {
/* this is truncate table */
mtr_commit(mtr);
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
}
if (scrub_data->current_index->page == FIL_NULL) {
/* this is truncate table */
mtr_commit(mtr);
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
}
buf_frame_t* frame = buf_block_get_frame(block);
if (!frame || btr_page_get_index_id(frame) !=
scrub_data->current_index->id) {
/* page has been reallocated to new index */
mtr_commit(mtr);
return BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE;
}
/* check if I can scrub (reorganize) page wo/ overflow */
if (btr_optimistic_scrub(scrub_data,
block,
scrub_data->current_index,
mtr) != DB_SUCCESS) {
/**
* Can't reorganize page...need to split it
*/
btr_pessimistic_scrub(scrub_data,
block,
scrub_data->current_index,
mtr);
}
mtr_commit(mtr);
return BTR_SCRUB_SKIP_PAGE; // no further action needed
}
/**************************************************************//**
Start iterating a space */
UNIV_INTERN
bool
btr_scrub_start_space(
/*===================*/
ulint space, /*!< in: space */
btr_scrub_t* scrub_data) /*!< in/out: scrub data */
{
scrub_data->space = space;
scrub_data->current_table = NULL;
scrub_data->current_index = NULL;
if (fil_space_t* s = fil_space_acquire_silent(space)) {
scrub_data->compressed = s->zip_size();
s->release();
} else {
scrub_data->compressed = 0;
}
scrub_data->scrubbing = check_scrub_setting(scrub_data);
return scrub_data->scrubbing;
}
/***********************************************************************
Update global statistics with thread statistics */
static
void
btr_scrub_update_total_stat(btr_scrub_t *scrub_data)
{
mutex_enter(&scrub_stat_mutex);
scrub_stat.page_reorganizations +=
scrub_data->scrub_stat.page_reorganizations;
scrub_stat.page_splits +=
scrub_data->scrub_stat.page_splits;
scrub_stat.page_split_failures_underflow +=
scrub_data->scrub_stat.page_split_failures_underflow;
scrub_stat.page_split_failures_out_of_filespace +=
scrub_data->scrub_stat.page_split_failures_out_of_filespace;
scrub_stat.page_split_failures_missing_index +=
scrub_data->scrub_stat.page_split_failures_missing_index;
scrub_stat.page_split_failures_unknown +=
scrub_data->scrub_stat.page_split_failures_unknown;
mutex_exit(&scrub_stat_mutex);
// clear stat
memset(&scrub_data->scrub_stat, 0, sizeof(scrub_data->scrub_stat));
}
/** Complete iterating a space.
@param[in,out] scrub_data scrub data */
UNIV_INTERN
void
btr_scrub_complete_space(btr_scrub_t* scrub_data)
{
ut_ad(scrub_data->scrubbing);
btr_scrub_table_close_for_thread(scrub_data);
btr_scrub_update_total_stat(scrub_data);
}
/*********************************************************************
Return scrub statistics */
void
btr_scrub_total_stat(btr_scrub_stat_t *stat)
{
mutex_enter(&scrub_stat_mutex);
*stat = scrub_stat;
mutex_exit(&scrub_stat_mutex);
}
/*********************************************************************
Init global variables */
UNIV_INTERN
void
btr_scrub_init()
{
mutex_create(LATCH_ID_SCRUB_STAT_MUTEX, &scrub_stat_mutex);
memset(&scrub_stat, 0, sizeof(scrub_stat));
}
/*********************************************************************
Cleanup globals */
UNIV_INTERN
void
btr_scrub_cleanup()
{
mutex_free(&scrub_stat_mutex);
}

View file

@ -37,7 +37,6 @@ Modified Jan Lindström jan.lindstrom@mariadb.com
#include "mtr0mtr.h"
#include "mtr0log.h"
#include "ut0ut.h"
#include "btr0scrub.h"
#include "fsp0fsp.h"
#include "fil0pagecompress.h"
#include <my_crypt.h>
@ -79,20 +78,12 @@ UNIV_INTERN uint srv_n_fil_crypt_iops = 100; // 10ms per iop
static uint srv_alloc_time = 3; // allocate iops for 3s at a time
static uint n_fil_crypt_iops_allocated = 0;
/** Variables for scrubbing */
extern uint srv_background_scrub_data_interval;
extern uint srv_background_scrub_data_check_interval;
#define DEBUG_KEYROTATION_THROTTLING 0
/** Statistics variables */
static fil_crypt_stat_t crypt_stat;
static ib_mutex_t crypt_stat_mutex;
/** Is background scrubbing enabled, defined on btr0scrub.cc */
extern my_bool srv_background_scrub_data_uncompressed;
extern my_bool srv_background_scrub_data_compressed;
/***********************************************************************
Check if a key needs rotation given a key_state
@param[in] crypt_data Encryption information
@ -1165,9 +1156,6 @@ struct rotate_thread_t {
fil_crypt_stat_t crypt_stat; // statistics
btr_scrub_t scrub_data; /* thread local data used by btr_scrub-functions
* when iterating pages of tablespace */
/** @return whether this thread should terminate */
bool should_shutdown() const {
switch (srv_shutdown_state) {
@ -1266,20 +1254,7 @@ fil_crypt_space_needs_rotation(
key_state->key_version,
key_state->rotate_key_age);
crypt_data->rotate_state.scrubbing.is_active =
btr_scrub_start_space(space->id, &state->scrub_data);
time_t diff = time(0) - crypt_data->rotate_state.scrubbing.
last_scrub_completed;
bool need_scrubbing =
(srv_background_scrub_data_uncompressed ||
srv_background_scrub_data_compressed) &&
crypt_data->rotate_state.scrubbing.is_active
&& diff >= 0
&& ulint(diff) >= srv_background_scrub_data_interval;
if (need_key_rotation == false && need_scrubbing == false) {
if (need_key_rotation == false) {
break;
}
@ -1728,69 +1703,6 @@ fil_crypt_get_page_throttle_func(
return block;
}
/***********************************************************************
Get block and allocation status
note: innodb locks fil_space_latch and then block when allocating page
but locks block and then fil_space_latch when freeing page.
@param[in,out] state Rotation state
@param[in] offset Page offset
@param[in,out] mtr Minitransaction
@param[out] allocation_status Allocation status
@param[out] sleeptime_ms Sleep time
@return block or NULL
*/
static
buf_block_t*
btr_scrub_get_block_and_allocation_status(
rotate_thread_t* state,
ulint offset,
mtr_t* mtr,
btr_scrub_page_allocation_status_t *allocation_status,
ulint* sleeptime_ms)
{
mtr_t local_mtr;
buf_block_t *block = NULL;
fil_space_t* space = state->space;
ut_ad(space->referenced());
mtr_start(&local_mtr);
*allocation_status = fseg_page_is_free(space, (uint32_t)offset) ?
BTR_SCRUB_PAGE_FREE :
BTR_SCRUB_PAGE_ALLOCATED;
if (*allocation_status == BTR_SCRUB_PAGE_FREE) {
/* this is easy case, we lock fil_space_latch first and
then block */
block = fil_crypt_get_page_throttle(state,
offset, mtr,
sleeptime_ms);
mtr_commit(&local_mtr);
} else {
/* page is allocated according to xdes */
/* release fil_space_latch *before* fetching block */
mtr_commit(&local_mtr);
/* NOTE: when we have locked dict_index_get_lock(),
* it's safe to release fil_space_latch and then fetch block
* as dict_index_get_lock() is needed to make tree modifications
* such as free-ing a page
*/
block = fil_crypt_get_page_throttle(state,
offset, mtr,
sleeptime_ms);
}
return block;
}
/***********************************************************************
Rotate one page
@param[in,out] key_state Key state
@ -1829,7 +1741,6 @@ fil_crypt_rotate_page(
offset, &mtr,
&sleeptime_ms)) {
bool modified = false;
int needs_scrubbing = BTR_SCRUB_SKIP_PAGE;
byte* frame = buf_block_get_frame(block);
const lsn_t block_lsn = mach_read_from_8(FIL_PAGE_LSN + frame);
uint kv = buf_page_get_key_version(frame, space->flags);
@ -1885,74 +1796,11 @@ fil_crypt_rotate_page(
state->min_key_version_found = kv;
}
}
needs_scrubbing = btr_page_needs_scrubbing(
&state->scrub_data, block,
BTR_SCRUB_PAGE_ALLOCATION_UNKNOWN);
}
mtr.commit();
lsn_t end_lsn = mtr.commit_lsn();
if (needs_scrubbing == BTR_SCRUB_PAGE) {
mtr.start();
/*
* refetch page and allocation status
*/
btr_scrub_page_allocation_status_t allocated;
block = btr_scrub_get_block_and_allocation_status(
state, offset, &mtr,
&allocated,
&sleeptime_ms);
if (block) {
mtr.set_named_space(space);
/* get required table/index and index-locks */
needs_scrubbing = btr_scrub_recheck_page(
&state->scrub_data, block, allocated, &mtr);
if (needs_scrubbing == BTR_SCRUB_PAGE) {
/* we need to refetch it once more now that we have
* index locked */
block = btr_scrub_get_block_and_allocation_status(
state, offset, &mtr,
&allocated,
&sleeptime_ms);
needs_scrubbing = btr_scrub_page(&state->scrub_data,
block, allocated,
&mtr);
}
/* NOTE: mtr is committed inside btr_scrub_recheck_page()
* and/or btr_scrub_page. This is to make sure that
* locks & pages are latched in corrected order,
* the mtr is in some circumstances restarted.
* (mtr_commit() + mtr_start())
*/
}
}
if (needs_scrubbing != BTR_SCRUB_PAGE) {
/* if page didn't need scrubbing it might be that cleanups
are needed. do those outside of any mtr to prevent deadlocks.
the information what kinds of cleanups that are needed are
encoded inside the needs_scrubbing, but this is opaque to
this function (except the value BTR_SCRUB_PAGE) */
btr_scrub_skip_page(&state->scrub_data, needs_scrubbing);
}
if (needs_scrubbing == BTR_SCRUB_TURNED_OFF) {
/* if we just detected that scrubbing was turned off
* update global state to reflect this */
ut_ad(crypt_data);
mutex_enter(&crypt_data->mutex);
crypt_data->rotate_state.scrubbing.is_active = false;
mutex_exit(&crypt_data->mutex);
}
if (modified) {
/* if we modified page, we take lsn from mtr */
@ -2137,31 +1985,14 @@ static void fil_crypt_complete_rotate_space(rotate_thread_t* state)
crypt_data->rotate_state.flushing = true;
crypt_data->min_key_version =
crypt_data->rotate_state.min_key_version_found;
}
/* inform scrubbing */
crypt_data->rotate_state.scrubbing.is_active = false;
mutex_exit(&crypt_data->mutex);
/* all threads must call btr_scrub_complete_space wo/ mutex held */
if (state->scrub_data.scrubbing) {
btr_scrub_complete_space(&state->scrub_data);
if (should_flush) {
/* only last thread updates last_scrub_completed */
ut_ad(crypt_data);
mutex_enter(&crypt_data->mutex);
crypt_data->rotate_state.scrubbing.
last_scrub_completed = time(0);
mutex_exit(&crypt_data->mutex);
}
}
if (should_flush) {
mutex_exit(&crypt_data->mutex);
fil_crypt_flush_space(state);
mutex_enter(&crypt_data->mutex);
crypt_data->rotate_state.flushing = false;
mutex_exit(&crypt_data->mutex);
} else {
mutex_exit(&crypt_data->mutex);
}
} else {
mutex_enter(&crypt_data->mutex);
@ -2194,8 +2025,6 @@ DECLARE_THREAD(fil_crypt_thread)(void*)
key_state_t new_state;
time_t wait_start = time(0);
while (!thr.should_shutdown()) {
/* wait for key state changes
@ -2213,17 +2042,6 @@ DECLARE_THREAD(fil_crypt_thread)(void*)
* a space*/
break;
}
time_t waited = time(0) - wait_start;
/* Break if we have waited the background scrub
internal and background scrubbing is enabled */
if (waited >= 0
&& ulint(waited) >= srv_background_scrub_data_check_interval
&& (srv_background_scrub_data_uncompressed
|| srv_background_scrub_data_compressed)) {
break;
}
}
recheck = false;
@ -2604,45 +2422,6 @@ fil_crypt_total_stat(
mutex_exit(&crypt_stat_mutex);
}
/*********************************************************************
Get scrub status for a space (used by information_schema)
@param[in] space Tablespace
@param[out] status Scrub status */
UNIV_INTERN
void
fil_space_get_scrub_status(
const fil_space_t* space,
struct fil_space_scrub_status_t* status)
{
memset(status, 0, sizeof(*status));
ut_ad(space->referenced());
fil_space_crypt_t* crypt_data = space->crypt_data;
status->space = space->id;
if (crypt_data != NULL) {
status->compressed = FSP_FLAGS_GET_ZIP_SSIZE(space->flags) > 0;
mutex_enter(&crypt_data->mutex);
status->last_scrub_completed =
crypt_data->rotate_state.scrubbing.last_scrub_completed;
if (crypt_data->rotate_state.active_threads > 0 &&
crypt_data->rotate_state.scrubbing.is_active) {
status->scrubbing = true;
status->current_scrub_started =
crypt_data->rotate_state.start_time;
status->current_scrub_active_threads =
crypt_data->rotate_state.active_threads;
status->current_scrub_page_number =
crypt_data->rotate_state.next_offset;
status->current_scrub_max_page_number =
crypt_data->rotate_state.max_offset;
}
mutex_exit(&crypt_data->mutex);
}
}
#endif /* UNIV_INNOCHECKSUM */
/**

View file

@ -213,14 +213,8 @@ static char* innodb_version_str = (char*) INNODB_VERSION_STR;
extern uint srv_fil_crypt_rotate_key_age;
extern uint srv_n_fil_crypt_iops;
extern my_bool srv_immediate_scrub_data_uncompressed;
extern my_bool srv_background_scrub_data_uncompressed;
extern my_bool srv_background_scrub_data_compressed;
extern uint srv_background_scrub_data_interval;
extern uint srv_background_scrub_data_check_interval;
#ifdef UNIV_DEBUG
my_bool innodb_evict_tables_on_commit_debug;
extern my_bool srv_scrub_force_testing;
#endif
/** Note we cannot use rec_format_enum because we do not allow
@ -1081,22 +1075,6 @@ static SHOW_VAR innodb_status_variables[]= {
{"encryption_n_temp_blocks_decrypted",
&export_vars.innodb_n_temp_blocks_decrypted, SHOW_LONGLONG},
/* scrubing */
{"scrub_background_page_reorganizations",
&export_vars.innodb_scrub_page_reorganizations, SHOW_SIZE_T},
{"scrub_background_page_splits", &export_vars.innodb_scrub_page_splits,
SHOW_SIZE_T},
{"scrub_background_page_split_failures_underflow",
&export_vars.innodb_scrub_page_split_failures_underflow, SHOW_SIZE_T},
{"scrub_background_page_split_failures_out_of_filespace",
&export_vars.innodb_scrub_page_split_failures_out_of_filespace,SHOW_SIZE_T},
{"scrub_background_page_split_failures_missing_index",
&export_vars.innodb_scrub_page_split_failures_missing_index, SHOW_SIZE_T},
{"scrub_background_page_split_failures_unknown",
&export_vars.innodb_scrub_page_split_failures_unknown, SHOW_SIZE_T},
{"encryption_num_key_requests", &export_vars.innodb_encryption_key_requests,
SHOW_LONGLONG},
{NullS, NullS, SHOW_LONG}
};
@ -3454,6 +3432,26 @@ static const char* innodb_page_cleaners_msg
= "The parameter innodb_page_cleaners is deprecated and has no effect.";
ulong srv_n_log_files;
static my_bool innodb_background_scrub_data_uncompressed;
static const char* innodb_background_scrub_data_uncompressed_msg
= "The parameter innodb_background_scrub_data_uncompressed is deprecated and has no effect.";
static my_bool innodb_background_scrub_data_compressed;
static const char* innodb_background_scrub_data_compressed_msg
= "The parameter innodb_background_scrub_data_compressed is deprecated and has no effect.";
static uint innodb_background_scrub_data_check_interval;
static const char* innodb_background_scrub_data_check_interval_msg
= "The parameter innodb_background_scrub_data_check_interval is deprecated and has no effect.";
static uint innodb_background_scrub_data_interval;
static const char* innodb_background_scrub_data_interval_msg
= "The parameter innodb_background_scrub_data_interval is deprecated and has no effect.";
} // namespace deprecated
/** Initialize, validate and normalize the InnoDB startup parameters.
@ -18934,6 +18932,46 @@ innodb_scrub_log_speed_warn(THD* thd, st_mysql_sys_var*, void*, const void*)
deprecated::innodb_scrub_log_speed_msg);
}
static void
innodb_background_scrub_data_uncompressed_warn(THD* thd, st_mysql_sys_var*,
void*, const void*)
{
push_warning_printf(
thd, Sql_condition::WARN_LEVEL_WARN,
HA_ERR_UNSUPPORTED,
deprecated::innodb_background_scrub_data_uncompressed_msg);
}
static void
innodb_background_scrub_data_compressed_warn(THD* thd, st_mysql_sys_var*,
void*, const void*)
{
push_warning_printf(
thd, Sql_condition::WARN_LEVEL_WARN,
HA_ERR_UNSUPPORTED,
deprecated::innodb_background_scrub_data_compressed_msg);
}
static void
innodb_background_scrub_data_check_interval_warn(
THD* thd, st_mysql_sys_var*, void*, const void*)
{
push_warning_printf(
thd, Sql_condition::WARN_LEVEL_WARN,
HA_ERR_UNSUPPORTED,
deprecated::innodb_background_scrub_data_check_interval_msg);
}
static void
innodb_background_scrub_data_interval_warn(
THD* thd, st_mysql_sys_var*, void*, const void*)
{
push_warning_printf(
thd, Sql_condition::WARN_LEVEL_WARN,
HA_ERR_UNSUPPORTED,
deprecated::innodb_background_scrub_data_interval_msg);
}
static SHOW_VAR innodb_status_variables_export[]= {
{"Innodb", (char*) &show_innodb_vars, SHOW_FUNC},
{NullS, NullS, SHOW_LONG}
@ -20151,8 +20189,7 @@ static MYSQL_SYSVAR_ENUM(encrypt_tables, srv_encrypt_tables,
static MYSQL_SYSVAR_UINT(encryption_threads, srv_n_fil_crypt_threads,
PLUGIN_VAR_RQCMDARG,
"Number of threads performing background key rotation and "
"scrubbing",
"Number of threads performing background key rotation ",
NULL,
innodb_encryption_threads_update,
srv_n_fil_crypt_threads, 0, UINT_MAX32, 0);
@ -20197,47 +20234,24 @@ static MYSQL_SYSVAR_BOOL(immediate_scrub_data_uncompressed,
NULL, NULL, FALSE);
static MYSQL_SYSVAR_BOOL(background_scrub_data_uncompressed,
srv_background_scrub_data_uncompressed,
0,
"Enable scrubbing of uncompressed data by "
"background threads (same as encryption_threads)",
NULL, NULL, FALSE);
deprecated::innodb_background_scrub_data_uncompressed,
PLUGIN_VAR_OPCMDARG, innodb_deprecated_ignored, NULL,
innodb_background_scrub_data_uncompressed_warn, FALSE);
static MYSQL_SYSVAR_BOOL(background_scrub_data_compressed,
srv_background_scrub_data_compressed,
0,
"Enable scrubbing of compressed data by "
"background threads (same as encryption_threads)",
NULL, NULL, FALSE);
deprecated::innodb_background_scrub_data_compressed,
PLUGIN_VAR_OPCMDARG, innodb_deprecated_ignored, NULL,
innodb_background_scrub_data_compressed_warn, FALSE);
static MYSQL_SYSVAR_UINT(background_scrub_data_check_interval,
srv_background_scrub_data_check_interval,
0,
"check if spaces needs scrubbing every "
"innodb_background_scrub_data_check_interval "
"seconds",
NULL, NULL,
srv_background_scrub_data_check_interval,
1,
UINT_MAX32, 0);
deprecated::innodb_background_scrub_data_check_interval,
0, innodb_deprecated_ignored, NULL,
innodb_background_scrub_data_check_interval_warn, 0, 0, 0, 0);
static MYSQL_SYSVAR_UINT(background_scrub_data_interval,
srv_background_scrub_data_interval,
0,
"scrub spaces that were last scrubbed longer than "
" innodb_background_scrub_data_interval seconds ago",
NULL, NULL,
srv_background_scrub_data_interval,
1,
UINT_MAX32, 0);
#ifdef UNIV_DEBUG
static MYSQL_SYSVAR_BOOL(debug_force_scrubbing,
srv_scrub_force_testing,
0,
"Perform extra scrubbing to increase test exposure",
NULL, NULL, FALSE);
#endif /* UNIV_DEBUG */
deprecated::innodb_background_scrub_data_interval,
0, innodb_deprecated_ignored, NULL,
innodb_background_scrub_data_interval_warn, 0, 0, 0, 0);
static MYSQL_SYSVAR_BOOL(encrypt_temporary_tables, innodb_encrypt_temporary_tables,
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
@ -20442,9 +20456,6 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(background_scrub_data_compressed),
MYSQL_SYSVAR(background_scrub_data_interval),
MYSQL_SYSVAR(background_scrub_data_check_interval),
#ifdef UNIV_DEBUG
MYSQL_SYSVAR(debug_force_scrubbing),
#endif
MYSQL_SYSVAR(buf_dump_status_frequency),
MYSQL_SYSVAR(background_thread),
MYSQL_SYSVAR(encrypt_temporary_tables),
@ -20499,8 +20510,7 @@ i_s_innodb_sys_datafiles,
i_s_innodb_sys_virtual,
i_s_innodb_mutexes,
i_s_innodb_sys_semaphore_waits,
i_s_innodb_tablespaces_encryption,
i_s_innodb_tablespaces_scrubbing
i_s_innodb_tablespaces_encryption
maria_declare_plugin_end;
/** @brief Initialize the default value of innodb_commit_concurrency.

View file

@ -7159,228 +7159,6 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_tablespaces_encryption =
STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
};
namespace Show {
/** TABLESPACES_SCRUBBING ********************************************/
/* Fields of the table INFORMATION_SCHEMA.INNODB_TABLESPACES_SCRUBBING */
static ST_FIELD_INFO innodb_tablespaces_scrubbing_fields_info[] =
{
#define TABLESPACES_SCRUBBING_SPACE 0
Column("SPACE", ULonglong(), NOT_NULL),
#define TABLESPACES_SCRUBBING_NAME 1
Column("NAME", Varchar(MAX_FULL_NAME_LEN + 1), NULLABLE),
#define TABLESPACES_SCRUBBING_COMPRESSED 2
Column("COMPRESSED", ULong(1), NOT_NULL),
#define TABLESPACES_SCRUBBING_LAST_SCRUB_COMPLETED 3
Column("LAST_SCRUB_COMPLETED", Datetime(0), NULLABLE),
#define TABLESPACES_SCRUBBING_CURRENT_SCRUB_STARTED 4
Column("CURRENT_SCRUB_STARTED", Datetime(0), NULLABLE),
#define TABLESPACES_SCRUBBING_CURRENT_SCRUB_ACTIVE_THREADS 5
Column("CURRENT_SCRUB_ACTIVE_THREADS", ULong(), NULLABLE),
#define TABLESPACES_SCRUBBING_CURRENT_SCRUB_PAGE_NUMBER 6
Column("CURRENT_SCRUB_PAGE_NUMBER", ULonglong(),NOT_NULL),
#define TABLESPACES_SCRUBBING_CURRENT_SCRUB_MAX_PAGE_NUMBER 7
Column("CURRENT_SCRUB_MAX_PAGE_NUMBER", ULonglong(), NOT_NULL),
#define TABLESPACES_SCRUBBING_ON_SSD 8
Column("ON_SSD", ULong(1), NOT_NULL),
CEnd()
};
} // namespace Show
/**********************************************************************//**
Function to fill INFORMATION_SCHEMA.INNODB_TABLESPACES_SCRUBBING
with information collected by scanning SYS_TABLESPACES table and
fil_space.
@param[in] thd Thread handle
@param[in] space Tablespace
@param[in] table_to_fill I_S table
@return 0 on success */
static
int
i_s_dict_fill_tablespaces_scrubbing(
THD* thd,
fil_space_t* space,
TABLE* table_to_fill)
{
Field** fields;
struct fil_space_scrub_status_t status;
DBUG_ENTER("i_s_dict_fill_tablespaces_scrubbing");
fields = table_to_fill->field;
fil_space_get_scrub_status(space, &status);
OK(fields[TABLESPACES_SCRUBBING_SPACE]->store(space->id, true));
OK(field_store_string(fields[TABLESPACES_SCRUBBING_NAME],
space->name));
OK(fields[TABLESPACES_SCRUBBING_COMPRESSED]->store(
status.compressed ? 1 : 0, true));
if (status.last_scrub_completed == 0) {
fields[TABLESPACES_SCRUBBING_LAST_SCRUB_COMPLETED]->set_null();
} else {
fields[TABLESPACES_SCRUBBING_LAST_SCRUB_COMPLETED]
->set_notnull();
OK(field_store_time_t(
fields[TABLESPACES_SCRUBBING_LAST_SCRUB_COMPLETED],
status.last_scrub_completed));
}
int field_numbers[] = {
TABLESPACES_SCRUBBING_CURRENT_SCRUB_STARTED,
TABLESPACES_SCRUBBING_CURRENT_SCRUB_ACTIVE_THREADS,
TABLESPACES_SCRUBBING_CURRENT_SCRUB_PAGE_NUMBER,
TABLESPACES_SCRUBBING_CURRENT_SCRUB_MAX_PAGE_NUMBER };
if (status.scrubbing) {
for (uint i = 0; i < array_elements(field_numbers); i++) {
fields[field_numbers[i]]->set_notnull();
}
OK(field_store_time_t(
fields[TABLESPACES_SCRUBBING_CURRENT_SCRUB_STARTED],
status.current_scrub_started));
OK(fields[TABLESPACES_SCRUBBING_CURRENT_SCRUB_ACTIVE_THREADS]
->store(status.current_scrub_active_threads, true));
OK(fields[TABLESPACES_SCRUBBING_CURRENT_SCRUB_PAGE_NUMBER]
->store(status.current_scrub_page_number, true));
OK(fields[TABLESPACES_SCRUBBING_CURRENT_SCRUB_MAX_PAGE_NUMBER]
->store(status.current_scrub_max_page_number, true));
} else {
for (uint i = 0; i < array_elements(field_numbers); i++) {
fields[field_numbers[i]]->set_null();
}
}
OK(fields[TABLESPACES_SCRUBBING_ON_SSD]->store(!space->is_rotational(),
true));
OK(schema_table_store_record(thd, table_to_fill));
DBUG_RETURN(0);
}
/*******************************************************************//**
Function to populate INFORMATION_SCHEMA.INNODB_TABLESPACES_SCRUBBING table.
Loop through each record in TABLESPACES_SCRUBBING, and extract the column
information and fill the INFORMATION_SCHEMA.INNODB_TABLESPACES_SCRUBBING table.
@return 0 on success */
static
int
i_s_tablespaces_scrubbing_fill_table(
/*===========================*/
THD* thd, /*!< in: thread */
TABLE_LIST* tables, /*!< in/out: tables to fill */
Item* ) /*!< in: condition (not used) */
{
DBUG_ENTER("i_s_tablespaces_scrubbing_fill_table");
RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str);
/* deny access to user without SUPER_ACL privilege */
if (check_global_access(thd, SUPER_ACL)) {
DBUG_RETURN(0);
}
mutex_enter(&fil_system.mutex);
for (fil_space_t* space = UT_LIST_GET_FIRST(fil_system.space_list);
space; space = UT_LIST_GET_NEXT(space_list, space)) {
if (space->purpose == FIL_TYPE_TABLESPACE
&& !space->is_stopping()) {
space->acquire();
mutex_exit(&fil_system.mutex);
if (int err = i_s_dict_fill_tablespaces_scrubbing(
thd, space, tables->table)) {
space->release();
DBUG_RETURN(err);
}
mutex_enter(&fil_system.mutex);
space->release();
}
}
mutex_exit(&fil_system.mutex);
DBUG_RETURN(0);
}
/*******************************************************************//**
Bind the dynamic table INFORMATION_SCHEMA.INNODB_TABLESPACES_SCRUBBING
@return 0 on success */
static
int
innodb_tablespaces_scrubbing_init(
/*========================*/
void* p) /*!< in/out: table schema object */
{
ST_SCHEMA_TABLE* schema;
DBUG_ENTER("innodb_tablespaces_scrubbing_init");
schema = (ST_SCHEMA_TABLE*) p;
schema->fields_info = Show::innodb_tablespaces_scrubbing_fields_info;
schema->fill_table = i_s_tablespaces_scrubbing_fill_table;
DBUG_RETURN(0);
}
UNIV_INTERN struct st_maria_plugin i_s_innodb_tablespaces_scrubbing =
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
/* int */
STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
/* pointer to type-specific plugin descriptor */
/* void* */
STRUCT_FLD(info, &i_s_info),
/* plugin name */
/* const char* */
STRUCT_FLD(name, "INNODB_TABLESPACES_SCRUBBING"),
/* plugin author (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(author, "Google Inc"),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD(descr, "InnoDB TABLESPACES_SCRUBBING"),
/* the plugin license (PLUGIN_LICENSE_XXX) */
/* int */
STRUCT_FLD(license, PLUGIN_LICENSE_BSD),
/* the function to invoke when plugin is loaded */
/* int (*)(void*); */
STRUCT_FLD(init, innodb_tablespaces_scrubbing_init),
/* the function to invoke when plugin is unloaded */
/* int (*)(void*); */
STRUCT_FLD(deinit, i_s_common_deinit),
/* plugin version (for SHOW PLUGINS) */
/* unsigned int */
STRUCT_FLD(version, INNODB_VERSION_SHORT),
/* struct st_mysql_show_var* */
STRUCT_FLD(status_vars, NULL),
/* struct st_mysql_sys_var** */
STRUCT_FLD(system_vars, NULL),
/* Maria extension */
STRUCT_FLD(version_info, INNODB_VERSION_STR),
STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE)
};
namespace Show {
/** INNODB_MUTEXES *********************************************/
/* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_MUTEXES */

View file

@ -1,157 +0,0 @@
// Copyright 2014 Google
#ifndef btr0scrub_h
#define btr0scrub_h
#include "dict0dict.h"
/**
* enum describing page allocation status
*/
enum btr_scrub_page_allocation_status_t {
BTR_SCRUB_PAGE_FREE,
BTR_SCRUB_PAGE_ALLOCATED,
BTR_SCRUB_PAGE_ALLOCATION_UNKNOWN
};
/**
* constants returned by btr_page_needs_scrubbing & btr_scrub_recheck_page
*/
#define BTR_SCRUB_PAGE 1 /* page should be scrubbed */
#define BTR_SCRUB_SKIP_PAGE 2 /* no scrub & no action */
#define BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE 3 /* no scrub & close table */
#define BTR_SCRUB_SKIP_PAGE_AND_COMPLETE_SPACE 4 /* no scrub & complete space */
#define BTR_SCRUB_TURNED_OFF 5 /* we detected that scrubbing
was disabled by global
variable */
/**************************************************************//**
struct for keeping scrub statistics. */
struct btr_scrub_stat_t {
/* page reorganizations */
ulint page_reorganizations;
/* page splits */
ulint page_splits;
/* scrub failures */
ulint page_split_failures_underflow;
ulint page_split_failures_out_of_filespace;
ulint page_split_failures_missing_index;
ulint page_split_failures_unknown;
};
/**************************************************************//**
struct for thread local scrub state. */
struct btr_scrub_t {
/* current space */
ulint space;
/* is scrubbing enabled for this space */
bool scrubbing;
/* is current space compressed */
bool compressed;
dict_table_t* current_table;
dict_index_t* current_index;
/* savepoint for X_LATCH of block */
ulint savepoint;
/* statistic counters */
btr_scrub_stat_t scrub_stat;
};
/*********************************************************************
Init scrub global variables */
UNIV_INTERN
void
btr_scrub_init();
/*********************************************************************
Cleanup scrub globals */
UNIV_INTERN
void
btr_scrub_cleanup();
/***********************************************************************
Return crypt statistics */
UNIV_INTERN
void
btr_scrub_total_stat(
/*==================*/
btr_scrub_stat_t *stat); /*!< out: stats to update */
/**************************************************************//**
Check if a page needs scrubbing
* @return BTR_SCRUB_PAGE if page should be scrubbed
* else btr_scrub_skip_page should be called
* with this return value (and without any latches held)
*/
UNIV_INTERN
int
btr_page_needs_scrubbing(
/*=====================*/
btr_scrub_t* scrub_data, /*!< in: scrub data */
buf_block_t* block, /*!< in: block to check, latched */
btr_scrub_page_allocation_status_t allocated); /*!< in: is block
allocated, free or
unknown */
/****************************************************************
Recheck if a page needs scrubbing, and if it does load appropriate
table and index
* @return BTR_SCRUB_PAGE if page should be scrubbed
* else btr_scrub_skip_page should be called
* with this return value (and without any latches held)
*/
UNIV_INTERN
int
btr_scrub_recheck_page(
/*====================*/
btr_scrub_t* scrub_data, /*!< inut: scrub data */
buf_block_t* block, /*!< in: block */
btr_scrub_page_allocation_status_t allocated, /*!< in: is block
allocated or free */
mtr_t* mtr); /*!< in: mtr */
/****************************************************************
Perform actual scrubbing of page */
UNIV_INTERN
int
btr_scrub_page(
/*============*/
btr_scrub_t* scrub_data, /*!< in/out: scrub data */
buf_block_t* block, /*!< in: block */
btr_scrub_page_allocation_status_t allocated, /*!< in: is block
allocated or free */
mtr_t* mtr); /*!< in: mtr */
/****************************************************************
Perform cleanup needed for a page not needing scrubbing */
UNIV_INTERN
void
btr_scrub_skip_page(
/*============*/
btr_scrub_t* scrub_data, /*!< in/out: scrub data */
int needs_scrubbing); /*!< in: return value from
btr_page_needs_scrubbing or
btr_scrub_recheck_page which encodes what kind
of cleanup is needed */
/****************************************************************
Start iterating a space
* @return true if scrubbing is turned on */
UNIV_INTERN
bool
btr_scrub_start_space(
/*===================*/
ulint space, /*!< in: space */
btr_scrub_t* scrub_data); /*!< in/out: scrub data */
/** Complete iterating a space.
@param[in,out] scrub_data scrub data */
UNIV_INTERN
void
btr_scrub_complete_space(btr_scrub_t* scrub_data);
#endif

View file

@ -93,11 +93,6 @@ struct fil_space_rotate_state_t
space */
bool starting; /*!< initial write of IV */
bool flushing; /*!< space is being flushed at end of rotate */
struct {
bool is_active; /*!< is scrubbing active in this space */
time_t last_scrub_completed; /*!< when was last scrub
completed */
} scrubbing;
};
#ifndef UNIV_INNOCHECKSUM
@ -226,18 +221,6 @@ struct fil_crypt_stat_t {
ulint estimated_iops;
};
/** Status info about scrubbing */
struct fil_space_scrub_status_t {
ulint space; /*!< tablespace id */
bool compressed; /*!< is space compressed */
time_t last_scrub_completed; /*!< when was last scrub completed */
bool scrubbing; /*!< is scrubbing ongoing */
time_t current_scrub_started; /*!< when started current scrubbing */
ulint current_scrub_active_threads; /*!< current scrub active threads */
ulint current_scrub_page_number; /*!< current scrub page no */
ulint current_scrub_max_page_number; /*!< current scrub max page no */
};
/*********************************************************************
Init space crypt */
UNIV_INTERN
@ -449,18 +432,6 @@ void
fil_crypt_total_stat(
fil_crypt_stat_t *stat);
/**
Get scrub status for a space (used by information_schema)
@param[in] space Tablespace
@param[out] status Scrub status
return 0 if data found */
UNIV_INTERN
void
fil_space_get_scrub_status(
const fil_space_t* space,
fil_space_scrub_status_t* status);
#include "fil0crypt.ic"
#endif /* !UNIV_INNOCHECKSUM */

View file

@ -454,6 +454,7 @@ extern ulong srv_replication_delay;
extern my_bool innodb_encrypt_temporary_tables;
extern my_bool srv_immediate_scrub_data_uncompressed;
/*-------------------------------------------*/
/** Modes of operation */
@ -958,13 +959,6 @@ struct export_var_t{
ulint innodb_encryption_rotation_estimated_iops;
int64_t innodb_encryption_key_requests;
int64_t innodb_key_rotation_list_length;
ulint innodb_scrub_page_reorganizations;
ulint innodb_scrub_page_splits;
ulint innodb_scrub_page_split_failures_underflow;
ulint innodb_scrub_page_split_failures_out_of_filespace;
ulint innodb_scrub_page_split_failures_missing_index;
ulint innodb_scrub_page_split_failures_unknown;
};
/** Thread slot in the thread table. */

View file

@ -72,7 +72,6 @@ Created 10/8/1995 Heikki Tuuri
#include "fil0fil.h"
#include "fil0crypt.h"
#include "fil0pagecompress.h"
#include "btr0scrub.h"
#include <my_service_manager.h>
@ -403,6 +402,8 @@ my_bool srv_force_primary_key;
/** Key version to encrypt the temporary tablespace */
my_bool innodb_encrypt_temporary_tables;
my_bool srv_immediate_scrub_data_uncompressed;
/* Array of English strings describing the current state of an
i/o handler thread */
@ -1113,11 +1114,9 @@ srv_export_innodb_status(void)
/*==========================*/
{
fil_crypt_stat_t crypt_stat;
btr_scrub_stat_t scrub_stat;
if (!srv_read_only_mode) {
fil_crypt_total_stat(&crypt_stat);
btr_scrub_total_stat(&scrub_stat);
}
#ifdef BTR_CUR_HASH_ADAPT
@ -1346,19 +1345,6 @@ srv_export_innodb_status(void)
srv_stats.n_key_requests;
export_vars.innodb_key_rotation_list_length =
srv_stats.key_rotation_list_length;
export_vars.innodb_scrub_page_reorganizations =
scrub_stat.page_reorganizations;
export_vars.innodb_scrub_page_splits =
scrub_stat.page_splits;
export_vars.innodb_scrub_page_split_failures_underflow =
scrub_stat.page_split_failures_underflow;
export_vars.innodb_scrub_page_split_failures_out_of_filespace =
scrub_stat.page_split_failures_out_of_filespace;
export_vars.innodb_scrub_page_split_failures_missing_index =
scrub_stat.page_split_failures_missing_index;
export_vars.innodb_scrub_page_split_failures_unknown =
scrub_stat.page_split_failures_unknown;
}
mutex_exit(&srv_innodb_monitor_mutex);

View file

@ -100,7 +100,6 @@ Created 2/16/1996 Heikki Tuuri
#include "os0event.h"
#include "zlib.h"
#include "ut0crc32.h"
#include "btr0scrub.h"
/** Log sequence number at shutdown */
lsn_t srv_shutdown_lsn;
@ -2028,7 +2027,6 @@ skip_monitors:
will flush dirty pages and that might need e.g.
fil_crypt_threads_event. */
fil_system_enter();
btr_scrub_init();
fil_crypt_threads_init();
fil_system_exit();
@ -2136,7 +2134,6 @@ void innodb_shutdown()
fts_optimize_shutdown(); dict_stats_shutdown(); */
fil_crypt_threads_cleanup();
btr_scrub_cleanup();
btr_defragment_shutdown();
}