Skip to content
/ server Public

Commit 4a9a384

Browse files
committed
WIP MDEV-37949: Implement innodb_log_archive, innodb_lsn_archived
The new setting SET GLOBAL innodb_log_archive=ON will enable log archiving as soon as the current ib_logfile0 is about to wrap around an odd number of times. The new status variable innodb_lsn_archived will return 0 when log archiving is not enabled, or a LSN since when a complete InnoDB log archive is available. When innodb_log_archive=ON, the setting SET GLOBAL innodb_log_file_size will affect subsequently created log files when the file that is being currently written is running out. log_t::archive_new_mmap(): Create and memory-map a new log file, and update file_size to resize_target. log_t::archive_set_size(): Ensure that resize_target is set for new archived log files. mtr_t::finish_writer(): Specialize for innodb_log_archive=ON TODO: Specialize log_t::resizing_and_latch (non-PMEM code path). TODO: Rename log files and set innodb_lsn_archived on checkpoint. TODO: Implement recovery from archived log.
1 parent 9496a62 commit 4a9a384

File tree

13 files changed

+220
-57
lines changed

13 files changed

+220
-57
lines changed

mysql-test/suite/innodb/r/innodb_status_variables.result

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ INNODB_LOG_WRITES
5151
INNODB_LSN_CURRENT
5252
INNODB_LSN_FLUSHED
5353
INNODB_LSN_LAST_CHECKPOINT
54+
INNODB_LSN_ARCHIVED
5455
INNODB_MASTER_THREAD_ACTIVE_LOOPS
5556
INNODB_MASTER_THREAD_IDLE_LOOPS
5657
INNODB_MAX_TRX_ID

mysql-test/suite/innodb/r/log_file_size_online.result

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
SET GLOBAL innodb_log_archive=OFF;
12
SET GLOBAL innodb_log_file_size=4194304;
23
SHOW VARIABLES LIKE 'innodb_log_file_size';
34
Variable_name Value
@@ -11,7 +12,7 @@ a INT PRIMARY KEY AUTO_INCREMENT,
1112
b CHAR(255) NOT NULL)
1213
ENGINE=INNODB;
1314
INSERT INTO t SELECT NULL, REPEAT('a', 255) FROM seq_1_to_20000;
14-
# restart: --innodb-log-file-size=4194304
15+
# restart: --innodb-log-file-size=4194304 --skip-innodb-log-archive
1516
SELECT COUNT(*) FROM t;
1617
COUNT(*)
1718
20000
@@ -28,8 +29,15 @@ Got one of the listed errors
2829
connect con1,localhost,root;
2930
SET GLOBAL innodb_log_file_size=7340032;
3031
connection default;
32+
SET GLOBAL innodb_log_archive=ON;
33+
SET GLOBAL innodb_log_archive=OFF;
3134
KILL QUERY @id;
3235
connection con1;
36+
SET GLOBAL innodb_log_archive=ON, innodb_log_file_size=10485760;
37+
SELECT @@GLOBAL.innodb_log_file_size!=10485760;
38+
@@GLOBAL.innodb_log_file_size!=10485760
39+
1
40+
SET GLOBAL innodb_log_archive=OFF;
3341
connection default;
3442
SET GLOBAL innodb_log_file_size=5242880;
3543
connection con1;
@@ -46,6 +54,8 @@ connection con1;
4654
disconnect con1;
4755
connection default;
4856
# restart
57+
SET @save_archive=@@GLOBAL.innodb_log_archive;
58+
SET GLOBAL innodb_log_archive=OFF;
4959
SELECT * FROM t WHERE a<10;
5060
a b
5161
1
@@ -73,4 +83,5 @@ SHOW VARIABLES LIKE 'innodb_log_file_size';
7383
Variable_name Value
7484
innodb_log_file_size 5242880
7585
FOUND 1 /InnoDB: Resized log to 6\.000MiB/ in mysqld.1.err
86+
SET GLOBAL innodb_log_archive=@save_archive;
7687
DROP TABLE t;

mysql-test/suite/innodb/t/innodb-master.opt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,3 @@
22
--default-storage-engine=MyISAM
33
--innodb-strict-mode=0
44
--innodb-file-per-table=0
5-
--loose-innodb-track-changed-pages
6-
--loose-innodb-log-archive
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
--skip-innodb-log-archive

mysql-test/suite/innodb/t/log_file_size_online.test

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44

55
let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.1.err;
66

7+
SET GLOBAL innodb_log_archive=OFF;
8+
let $wait_condition=
9+
SELECT variable_value = 0
10+
FROM information_schema.global_status
11+
WHERE variable_name = 'innodb_lsn_archived';
12+
--source include/wait_condition.inc
13+
714
SET GLOBAL innodb_log_file_size=4194304;
815
SHOW VARIABLES LIKE 'innodb_log_file_size';
916
SELECT global_value FROM information_schema.system_variables
@@ -16,7 +23,7 @@ ENGINE=INNODB;
1623

1724
INSERT INTO t SELECT NULL, REPEAT('a', 255) FROM seq_1_to_20000;
1825

19-
--let $restart_parameters=--innodb-log-file-size=4194304
26+
--let $restart_parameters=--innodb-log-file-size=4194304 --skip-innodb-log-archive
2027
--source include/restart_mysqld.inc
2128

2229
SELECT COUNT(*) FROM t;
@@ -41,10 +48,20 @@ let $ID= `SELECT @id := CONNECTION_ID()`;
4148
send SET GLOBAL innodb_log_file_size=7340032;
4249
--connection default
4350
let $ignore= `SELECT @id := $ID`;
51+
--error 0,ER_WRONG_USAGE
52+
SET GLOBAL innodb_log_archive=ON;
53+
SET GLOBAL innodb_log_archive=OFF;
54+
4455
KILL QUERY @id;
4556
--connection con1
4657
reap;
4758

59+
# When innodb_log_archive=ON, SET GLOBAL innodb_log_file_size is instantaneous
60+
# but will not reflect the file size.
61+
SET GLOBAL innodb_log_archive=ON, innodb_log_file_size=10485760;
62+
SELECT @@GLOBAL.innodb_log_file_size!=10485760;
63+
SET GLOBAL innodb_log_archive=OFF;
64+
4865
--connection default
4966
send SET GLOBAL innodb_log_file_size=5242880;
5067

@@ -66,6 +83,14 @@ reap;
6683
--let $restart_parameters=
6784
--source include/restart_mysqld.inc
6885

86+
SET @save_archive=@@GLOBAL.innodb_log_archive;
87+
SET GLOBAL innodb_log_archive=OFF;
88+
let $wait_condition=
89+
SELECT variable_value = 0
90+
FROM information_schema.global_status
91+
WHERE variable_name = 'innodb_lsn_archived';
92+
--source include/wait_condition.inc
93+
6994
SELECT * FROM t WHERE a<10;
7095
SELECT COUNT(*),LENGTH(b) FROM t GROUP BY b;
7196

@@ -76,5 +101,6 @@ SET GLOBAL innodb_log_file_size=5242880;
76101
SHOW VARIABLES LIKE 'innodb_log_file_size';
77102
let SEARCH_PATTERN = InnoDB: Resized log to 6\\.000MiB;
78103
--source include/search_pattern_in_file.inc
104+
SET GLOBAL innodb_log_archive=@save_archive;
79105

80106
DROP TABLE t;

mysql-test/suite/sys_vars/r/sysvars_innodb.result

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,18 @@ NUMERIC_BLOCK_SIZE 0
932932
ENUM_VALUE_LIST NULL
933933
READ_ONLY NO
934934
COMMAND_LINE_ARGUMENT REQUIRED
935+
VARIABLE_NAME INNODB_LOG_ARCHIVE
936+
SESSION_VALUE NULL
937+
DEFAULT_VALUE OFF
938+
VARIABLE_SCOPE GLOBAL
939+
VARIABLE_TYPE BOOLEAN
940+
VARIABLE_COMMENT Whether log archiving is desired (innodb_lsn_archived>0 if enabled)
941+
NUMERIC_MIN_VALUE NULL
942+
NUMERIC_MAX_VALUE NULL
943+
NUMERIC_BLOCK_SIZE NULL
944+
ENUM_VALUE_LIST OFF,ON
945+
READ_ONLY NO
946+
COMMAND_LINE_ARGUMENT OPTIONAL
935947
VARIABLE_NAME INNODB_LOG_BUFFER_SIZE
936948
SESSION_VALUE NULL
937949
DEFAULT_VALUE 16777216
@@ -973,7 +985,7 @@ SESSION_VALUE NULL
973985
DEFAULT_VALUE 100663296
974986
VARIABLE_SCOPE GLOBAL
975987
VARIABLE_TYPE BIGINT UNSIGNED
976-
VARIABLE_COMMENT Redo log size in bytes.
988+
VARIABLE_COMMENT Desired size of ib_logfile0 in bytes
977989
NUMERIC_MIN_VALUE 4194304
978990
NUMERIC_MAX_VALUE 18446744073709551615
979991
NUMERIC_BLOCK_SIZE 4096

sql/upgrade_conf_file.cc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ static const char *removed_variables[] =
9797
"innodb_locks_unsafe_for_binlog",
9898
"innodb_log_arch_dir",
9999
"innodb_log_arch_expire_sec",
100-
"innodb_log_archive",
101100
"innodb_log_block_size",
102101
"innodb_log_checksum_algorithm",
103102
"innodb_log_checksums",

storage/innobase/handler/ha_innodb.cc

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,7 @@ static SHOW_VAR innodb_status_variables[]= {
950950
{"lsn_flushed", &export_vars.innodb_lsn_flushed, SHOW_ULONGLONG},
951951
{"lsn_last_checkpoint", &export_vars.innodb_lsn_last_checkpoint,
952952
SHOW_ULONGLONG},
953+
{"lsn_archived", &log_sys.archived_lsn, SHOW_ULONGLONG},
953954
{"master_thread_active_loops", &srv_main_active_loops, SHOW_SIZE_T},
954955
{"master_thread_idle_loops", &srv_main_idle_loops, SHOW_SIZE_T},
955956
{"max_trx_id", &export_vars.innodb_max_trx_id, SHOW_ULONGLONG},
@@ -19430,6 +19431,34 @@ static MYSQL_SYSVAR_BOOL(data_file_write_through, fil_system.write_through,
1943019431
"Whether each write to data files writes through",
1943119432
nullptr, innodb_data_file_write_through_update, FALSE);
1943219433

19434+
static void innodb_log_archive_update(THD *, st_mysql_sys_var*,
19435+
void *, const void *save) noexcept
19436+
{
19437+
const my_bool archive= *static_cast<const my_bool*>(save);
19438+
log_sys.latch.wr_lock(SRW_LOCK_CALL);
19439+
const lsn_t resizing{log_sys.resize_in_progress()};
19440+
if (archive && UNIV_UNLIKELY(resizing != 0))
19441+
my_printf_error(ER_WRONG_USAGE,
19442+
"SET GLOBAL innodb_log_file_size is in progress", MYF(0));
19443+
else
19444+
{
19445+
log_sys.archive= archive;
19446+
if (!resizing)
19447+
{
19448+
if (archive)
19449+
log_sys.archive_set_size();
19450+
mtr_t::finisher_update();
19451+
}
19452+
}
19453+
log_sys.archived_lsn= 0; // FIXME: move this to log_t::write_checkpoint()
19454+
log_sys.latch.wr_unlock();
19455+
}
19456+
19457+
static MYSQL_SYSVAR_BOOL(log_archive, log_sys.archive,
19458+
PLUGIN_VAR_OPCMDARG,
19459+
"Whether log archiving is desired (innodb_lsn_archived>0 if enabled)",
19460+
nullptr, innodb_log_archive_update, FALSE);
19461+
1943319462
static MYSQL_SYSVAR_UINT64_T(log_recovery_start, recv_sys.recovery_start,
1943419463
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
1943519464
"checkpoint LSN to start recovery from (0=automatic)",
@@ -19442,7 +19471,7 @@ static MYSQL_SYSVAR_UINT64_T(log_recovery_target, recv_sys.rpo,
1944219471

1944319472
static MYSQL_SYSVAR_ULONGLONG(log_file_size, srv_log_file_size,
1944419473
PLUGIN_VAR_RQCMDARG,
19445-
"Redo log size in bytes.",
19474+
"Desired size of ib_logfile0 in bytes",
1944619475
nullptr, innodb_log_file_size_update,
1944719476
96 << 20, 4 << 20, std::numeric_limits<ulonglong>::max(), 4096);
1944819477

@@ -19874,6 +19903,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
1987419903
MYSQL_SYSVAR(log_file_write_through),
1987519904
MYSQL_SYSVAR(data_file_buffering),
1987619905
MYSQL_SYSVAR(data_file_write_through),
19906+
MYSQL_SYSVAR(log_archive),
1987719907
MYSQL_SYSVAR(log_recovery_start),
1987819908
MYSQL_SYSVAR(log_recovery_target),
1987919909
MYSQL_SYSVAR(log_file_size),

storage/innobase/include/log0log.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,13 +247,16 @@ struct log_t
247247
lsn_t (*writer)() noexcept;
248248
/** next checkpoint LSN (protected by latch.wr_lock()) */
249249
lsn_t next_checkpoint_lsn;
250+
/** start of archived log, or 0 (proteted by latch.wr_lock()) */
251+
lsn_t archived_lsn;
250252

251253
/** Log file */
252254
log_file_t log;
253255
private:
254256
/** Log file being constructed during resizing; protected by latch */
255257
log_file_t resize_log;
256-
/** size of resize_log; protected by latch */
258+
/** size of resize_log, or the requested innodb_log_file_size
259+
of the next file created if archive==TRUE; protected by latch */
257260
lsn_t resize_target;
258261
/** Buffer for writing to resize_log; @see buf */
259262
byte *resize_buf;
@@ -270,6 +273,8 @@ struct log_t
270273
uint write_size;
271274
/** format of the redo log: e.g., FORMAT_10_8 */
272275
uint32_t format;
276+
/** the current value of innodb_log_archive; protected by latch.wr_lock() */
277+
my_bool archive;
273278
/** whether the memory-mapped interface is enabled for the log */
274279
my_bool log_mmap;
275280
/** the default value of log_mmap */
@@ -455,8 +460,19 @@ struct log_t
455460
/** Persist the log.
456461
@param lsn desired new value of flushed_to_disk_lsn */
457462
void persist(lsn_t lsn) noexcept;
463+
/** Create, allocate and map a new log file. */
464+
ATTRIBUTE_COLD void archive_new_mmap() noexcept;
458465
#endif
459466

467+
/** Ensure that innodb_log_archive=ON will default to the current
468+
innodb_log_file_size if no size has been specified. */
469+
void archive_set_size() noexcept
470+
{
471+
ut_ad(!resize_in_progress());
472+
if (!resize_target)
473+
resize_target= file_size;
474+
}
475+
460476
bool check_for_checkpoint() const
461477
{
462478
return UNIV_UNLIKELY(need_checkpoint.load(std::memory_order_relaxed));

storage/innobase/include/mtr0mtr.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -701,12 +701,22 @@ struct mtr_t {
701701
@return {start_lsn,flush_ahead_lsn} */
702702
std::pair<lsn_t,lsn_t> do_write() noexcept;
703703

704+
/** How to write log */
705+
enum finish_writing {
706+
/** circular memory-mapped writing when log_sys.is_mmap() */
707+
CIRCULAR_MMAP,
708+
/** memory-mapped log for log_sys.archive */
709+
ARCHIVED_MMAP,
710+
/** normal writing !log_sys.is_mmap() */
711+
WRITE_NORMAL
712+
};
713+
704714
/** Append the redo log records to the redo log buffer.
705-
@tparam mmap log_sys.is_mmap()
715+
@tparam how how to write
706716
@param mtr mini-transaction
707717
@param len number of bytes to write
708718
@return {start_lsn,flush_ahead_lsn} */
709-
template<bool mmap> static
719+
template<finish_writing how> static
710720
std::pair<lsn_t,lsn_t> finish_writer(mtr_t *mtr, size_t len);
711721

712722
/** The applicable variant of commit_log() */

0 commit comments

Comments
 (0)