Commit 5c46751f authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-27734 Set innodb_change_buffering=none by default

The aim of the InnoDB change buffer is to avoid delays when a leaf page
of a secondary index is not present in the buffer pool, and a record needs
to be inserted, delete-marked, or purged. Instead of reading the page into
the buffer pool for making such a modification, we may insert a record to
the change buffer (a special index tree in the InnoDB system tablespace).
The buffered changes are guaranteed to be merged if the index page
actually needs to be read later.

The change buffer could be useful when the database is stored on a
rotational medium (hard disk) where random seeks are slower than
sequential reads or writes.

Obviously, the change buffer will cause write amplification, due to
potentially large amount of metadata that is being written to the
change buffer. We will have to write redo log records for modifying
the change buffer tree as well as the user tablespace. Furthermore,
in the user tablespace, we must maintain a change buffer bitmap page
that uses 2 bits for estimating the amount of free space in pages,
and 1 bit to specify whether buffered changes exist. This bitmap needs
to be updated on every operation, which could reduce performance.

Even if the change buffer were free of bugs such as MDEV-24449
(potentially causing the corruption of any page in the system tablespace)
or MDEV-26977 (corruption of secondary indexes due to a currently
unknown reason), it will make diagnosis of other data corruption harder.

Because of all this, it is best to disable the change buffer by default.
parent f7704d74
...@@ -5,6 +5,7 @@ c INT, ...@@ -5,6 +5,7 @@ c INT,
INDEX(b)) INDEX(b))
ENGINE=InnoDB STATS_PERSISTENT=0; ENGINE=InnoDB STATS_PERSISTENT=0;
SET GLOBAL innodb_change_buffering_debug = 1; SET GLOBAL innodb_change_buffering_debug = 1;
SET GLOBAL innodb_change_buffering=all;
INSERT INTO t1 SELECT 0,'x',1 FROM seq_1_to_1024; INSERT INTO t1 SELECT 0,'x',1 FROM seq_1_to_1024;
# restart: --innodb-force-recovery=6 --innodb-change-buffer-dump # restart: --innodb-force-recovery=6 --innodb-change-buffer-dump
check table t1; check table t1;
......
...@@ -13,6 +13,7 @@ c INT, ...@@ -13,6 +13,7 @@ c INT,
INDEX(b)) INDEX(b))
ENGINE=InnoDB STATS_PERSISTENT=0; ENGINE=InnoDB STATS_PERSISTENT=0;
SET GLOBAL innodb_change_buffering_debug = 1; SET GLOBAL innodb_change_buffering_debug = 1;
SET GLOBAL innodb_change_buffering = all;
INSERT INTO t1 SELECT 0,'x',1 FROM seq_1_to_8192; INSERT INTO t1 SELECT 0,'x',1 FROM seq_1_to_8192;
BEGIN; BEGIN;
SELECT b FROM t1 LIMIT 3; SELECT b FROM t1 LIMIT 3;
......
...@@ -24,6 +24,7 @@ ENGINE=InnoDB STATS_PERSISTENT=0; ...@@ -24,6 +24,7 @@ ENGINE=InnoDB STATS_PERSISTENT=0;
# change buffering is possible, so that the change buffer will be used # change buffering is possible, so that the change buffer will be used
# whenever possible. # whenever possible.
SET GLOBAL innodb_change_buffering_debug = 1; SET GLOBAL innodb_change_buffering_debug = 1;
SET GLOBAL innodb_change_buffering=all;
# Create enough rows for the table, so that the change buffer will be # Create enough rows for the table, so that the change buffer will be
# used for modifying the secondary index page. There must be multiple # used for modifying the secondary index page. There must be multiple
......
...@@ -33,6 +33,7 @@ ENGINE=InnoDB STATS_PERSISTENT=0; ...@@ -33,6 +33,7 @@ ENGINE=InnoDB STATS_PERSISTENT=0;
# change buffering is possible, so that the change buffer will be used # change buffering is possible, so that the change buffer will be used
# whenever possible. # whenever possible.
SET GLOBAL innodb_change_buffering_debug = 1; SET GLOBAL innodb_change_buffering_debug = 1;
SET GLOBAL innodb_change_buffering = all;
let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.1.err; let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.1.err;
# Create enough rows for the table, so that the change buffer will be # Create enough rows for the table, so that the change buffer will be
......
SET @start_global_value = @@global.innodb_change_buffering; SET @start_global_value = @@global.innodb_change_buffering;
SELECT @start_global_value; SELECT @start_global_value;
@start_global_value @start_global_value
all none
Valid values are 'all', 'deletes', 'changes', 'inserts', 'none', 'purges' Valid values are 'all', 'deletes', 'changes', 'inserts', 'none', 'purges'
select @@global.innodb_change_buffering in ('all', 'deletes', 'changes', 'inserts', 'none', 'purges'); select @@global.innodb_change_buffering in ('all', 'deletes', 'changes', 'inserts', 'none', 'purges');
@@global.innodb_change_buffering in ('all', 'deletes', 'changes', 'inserts', 'none', 'purges') @@global.innodb_change_buffering in ('all', 'deletes', 'changes', 'inserts', 'none', 'purges')
1 1
select @@global.innodb_change_buffering; select @@global.innodb_change_buffering;
@@global.innodb_change_buffering @@global.innodb_change_buffering
all none
select @@session.innodb_change_buffering; select @@session.innodb_change_buffering;
ERROR HY000: Variable 'innodb_change_buffering' is a GLOBAL variable ERROR HY000: Variable 'innodb_change_buffering' is a GLOBAL variable
show global variables like 'innodb_change_buffering'; show global variables like 'innodb_change_buffering';
Variable_name Value Variable_name Value
innodb_change_buffering all innodb_change_buffering none
show session variables like 'innodb_change_buffering'; show session variables like 'innodb_change_buffering';
Variable_name Value Variable_name Value
innodb_change_buffering all innodb_change_buffering none
select * from information_schema.global_variables where variable_name='innodb_change_buffering'; select * from information_schema.global_variables where variable_name='innodb_change_buffering';
VARIABLE_NAME VARIABLE_VALUE VARIABLE_NAME VARIABLE_VALUE
INNODB_CHANGE_BUFFERING all INNODB_CHANGE_BUFFERING none
select * from information_schema.session_variables where variable_name='innodb_change_buffering'; select * from information_schema.session_variables where variable_name='innodb_change_buffering';
VARIABLE_NAME VARIABLE_VALUE VARIABLE_NAME VARIABLE_VALUE
INNODB_CHANGE_BUFFERING all INNODB_CHANGE_BUFFERING none
set global innodb_change_buffering='none'; set global innodb_change_buffering='none';
select @@global.innodb_change_buffering; select @@global.innodb_change_buffering;
@@global.innodb_change_buffering @@global.innodb_change_buffering
...@@ -62,4 +62,4 @@ ERROR 42000: Variable 'innodb_change_buffering' can't be set to the value of 'so ...@@ -62,4 +62,4 @@ ERROR 42000: Variable 'innodb_change_buffering' can't be set to the value of 'so
SET @@global.innodb_change_buffering = @start_global_value; SET @@global.innodb_change_buffering = @start_global_value;
SELECT @@global.innodb_change_buffering; SELECT @@global.innodb_change_buffering;
@@global.innodb_change_buffering @@global.innodb_change_buffering
all none
...@@ -311,7 +311,7 @@ READ_ONLY NO ...@@ -311,7 +311,7 @@ READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME INNODB_CHANGE_BUFFERING VARIABLE_NAME INNODB_CHANGE_BUFFERING
SESSION_VALUE NULL SESSION_VALUE NULL
DEFAULT_VALUE all DEFAULT_VALUE none
VARIABLE_SCOPE GLOBAL VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE ENUM VARIABLE_TYPE ENUM
VARIABLE_COMMENT Buffer changes to secondary indexes. VARIABLE_COMMENT Buffer changes to secondary indexes.
......
...@@ -19623,7 +19623,7 @@ static MYSQL_SYSVAR_BOOL(numa_interleave, srv_numa_interleave, ...@@ -19623,7 +19623,7 @@ static MYSQL_SYSVAR_BOOL(numa_interleave, srv_numa_interleave,
static MYSQL_SYSVAR_ENUM(change_buffering, innodb_change_buffering, static MYSQL_SYSVAR_ENUM(change_buffering, innodb_change_buffering,
PLUGIN_VAR_RQCMDARG, PLUGIN_VAR_RQCMDARG,
"Buffer changes to secondary indexes.", "Buffer changes to secondary indexes.",
NULL, NULL, IBUF_USE_ALL, &innodb_change_buffering_typelib); NULL, NULL, IBUF_USE_NONE, &innodb_change_buffering_typelib);
static MYSQL_SYSVAR_UINT(change_buffer_max_size, static MYSQL_SYSVAR_UINT(change_buffer_max_size,
srv_change_buffer_max_size, srv_change_buffer_max_size,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment