mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-34705: Binlog in Engine: Fix re-using ids for binlog tablespaces
Before creating the next binlog tablespace N+2, flush out and close the old binlog tablespace N, so that the new tablespace can re-use the tablespace id without conflict. Signed-off-by: Kristian Nielsen <knielsen@knielsen-hq.org>
This commit is contained in:
@@ -14,11 +14,15 @@ SELECT @@GLOBAL.binlog_checksum;
|
||||
CREATE TABLE t2 (a INT PRIMARY KEY, b VARCHAR(2048)) ENGINE=InnoDB;
|
||||
|
||||
SET SESSION binlog_format= ROW;
|
||||
--let num_trx= 1500
|
||||
--echo *** Do $num_trx transactions ...
|
||||
--disable_query_log
|
||||
--let $i= 0
|
||||
while ($i < 500) {
|
||||
while ($i < 1500) {
|
||||
eval INSERT INTO t2 VALUES ($i, REPEAT("x", 2048));
|
||||
inc $i;
|
||||
}
|
||||
--enable_query_log
|
||||
SET SESSION binlog_format= MIXED;
|
||||
|
||||
DROP TABLE t2;
|
||||
|
@@ -25,6 +25,7 @@ Created 11/29/1995 Heikki Tuuri
|
||||
***********************************************************************/
|
||||
|
||||
#include "fsp0fsp.h"
|
||||
#include "buf0flu.h"
|
||||
#include "fil0crypt.h"
|
||||
#include "mtr0log.h"
|
||||
#include "page0page.h"
|
||||
@@ -4279,8 +4280,53 @@ uint32_t binlog_cur_page_offset= FIL_PAGE_DATA;
|
||||
/* ToDo: This needs to discover existing binlogs and start from the next free index. */
|
||||
uint64_t binlog_file_no= 0;
|
||||
|
||||
|
||||
/* '.' + '/' + "binlog" + '-' + (<=20 digits) + '.' + "ibb" + '\0'. */
|
||||
#define BINLOG_NAME_LEN 1 + 1 + 6 + 1 + 20 + 1 + 3 + 1
|
||||
static inline void
|
||||
binlog_name_make(char name_buf[BINLOG_NAME_LEN], uint64_t file_no)
|
||||
{
|
||||
sprintf(name_buf, "./binlog-%06" PRIu64 ".ibb", file_no);
|
||||
}
|
||||
|
||||
|
||||
/** Write out all pages, flush, and close/detach a binlog tablespace.
|
||||
@param[in] file_no Index of the binlog tablespace
|
||||
@return DB_SUCCESS or error code */
|
||||
static dberr_t
|
||||
fsp_binlog_tablespace_close(uint64_t file_no)
|
||||
{
|
||||
dberr_t res;
|
||||
|
||||
uint32_t space_id= SRV_SPACE_ID_BINLOG0 + (file_no & 1);
|
||||
mysql_mutex_lock(&fil_system.mutex);
|
||||
fil_space_t *space= fil_space_get_by_id(space_id);
|
||||
mysql_mutex_unlock(&fil_system.mutex);
|
||||
if (!space) {
|
||||
res= DB_ERROR;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
Write out any remaining pages in the buffer pool to the binlog tablespace.
|
||||
Then flush the file to disk, and close the old tablespace.
|
||||
*/
|
||||
while (buf_flush_list_space(space))
|
||||
;
|
||||
os_aio_wait_until_no_pending_writes(false);
|
||||
space->flush<false>();
|
||||
mysql_mutex_lock(&fil_system.mutex);
|
||||
fil_system.detach(space, false);
|
||||
mysql_mutex_unlock(&fil_system.mutex);
|
||||
|
||||
res= DB_SUCCESS;
|
||||
end:
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/** Create a binlog tablespace file
|
||||
@param[in] name file name
|
||||
@param[in] file_no Index of the binlog tablespace
|
||||
@return DB_SUCCESS or error code */
|
||||
dberr_t fsp_binlog_tablespace_create(uint64_t file_no)
|
||||
{
|
||||
@@ -4291,8 +4337,8 @@ dberr_t fsp_binlog_tablespace_create(uint64_t file_no)
|
||||
if(srv_read_only_mode)
|
||||
return DB_ERROR;
|
||||
|
||||
char name[1 + 1 + 6 + 1 + 20 + 1 + 3 + 1];
|
||||
sprintf(name, "./binlog-%06" PRIu64 ".ibb", file_no);
|
||||
char name[BINLOG_NAME_LEN];
|
||||
binlog_name_make(name, file_no);
|
||||
|
||||
os_file_create_subdirs_if_needed(name);
|
||||
|
||||
@@ -4410,6 +4456,23 @@ void fsp_binlog_write_cache(IO_CACHE *cache, size_t main_size, mtr_t *mtr)
|
||||
while (remain > 0) {
|
||||
if (page_offset == FIL_PAGE_DATA) {
|
||||
if (UNIV_UNLIKELY(!space) || page_no >= space->size) {
|
||||
/*
|
||||
Flush out to disk and close the old (N-2) tablespace so that we can
|
||||
re-use its tablespace id for the new one.
|
||||
|
||||
ToDo: Start this operation in the background as soon as the (N-2)
|
||||
tablespace has been filled, to avoid stalling here.
|
||||
|
||||
ToDo: Handle recovery. Idea: write the current LSN at the start of
|
||||
the binlog tablespace when we create it. At recovery, we should open
|
||||
the (at most) 2 most recent binlog tablespaces. Whenever we have a
|
||||
redo record, skip it if its LSN is smaller than the one stored in the
|
||||
tablespace corresponding to its space_id. This way, it should be safe
|
||||
to re-use tablespace ids between just two, SRV_SPACE_ID_BINLOG0 and
|
||||
SRV_SPACE_ID_BINLOG1.
|
||||
*/
|
||||
if (binlog_file_no >= 2)
|
||||
fsp_binlog_tablespace_close(binlog_file_no - 2);
|
||||
/*
|
||||
Create a new binlog tablespace.
|
||||
ToDo: pre-create the next tablespace in a background thread, avoiding
|
||||
|
Reference in New Issue
Block a user