mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
Implement an improved binlog implementation that is integrated into the storage engine. The new implementation is enabled with the --binlog-storage-engine option. Initially the InnoDB storage engine implements the binlog. Integrating the binlog in the storage engine improves performance, since it makes the InnoDB redo log the single source of truth and avoids the need for expensive two-phase commit between binlog and engine. It also makes it possible to disable durability (set --innodb-flush-log-at-trx-commit=0) to further improve performance, while still preserving the ability to recover the binlog and database into a consistent state after a crash. The new binlog implementation also greatly improves the internal design and implementation of the binlog, and enables future enhancements for replication. This is a squash of the original 11.4-based patch series. Signed-off-by: Kristian Nielsen <knielsen@knielsen-hq.org>
131 lines
4.0 KiB
C++
131 lines
4.0 KiB
C++
/* Copyright (c) 2013,2024, Kristian Nielsen and MariaDB Services Ab.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; version 2 of the License.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
|
|
|
|
#ifndef RPL_GTID_BASE_H
|
|
#define RPL_GTID_BASE_H
|
|
|
|
#include "hash.h"
|
|
|
|
|
|
/* Definitions for MariaDB global transaction ID (GTID). */
|
|
|
|
struct slave_connection_state;
|
|
|
|
struct rpl_gtid
|
|
{
|
|
uint32 domain_id;
|
|
uint32 server_id;
|
|
uint64 seq_no;
|
|
};
|
|
|
|
/*
|
|
Binlog state.
|
|
|
|
A binlog state records the last GTID written to the binlog for every
|
|
distinct (domain_id, server_id) pair. Thus, each point in the binlog
|
|
corresponds to a specific binlog state.
|
|
|
|
When starting replication from a specific GTID position, the starting point
|
|
is identified as the most recent one where the binlog state has no higher
|
|
seq_no than the GTID position for any (domain_id, server_id) combination.
|
|
|
|
We also remember the most recent logged GTID for every domain_id. This is
|
|
used to know where to start when a master is changed to a slave. As a side
|
|
effect, it also allows to skip a hash lookup in the very common case of
|
|
logging a new GTID with same server id as last GTID.
|
|
|
|
This base class rpl_binlog_state_base contains just be basic data operations
|
|
to insert/update GTIDs, and is used eg. from Gtid_index_*.
|
|
*/
|
|
struct rpl_binlog_state_base
|
|
{
|
|
struct element {
|
|
uint32 domain_id;
|
|
HASH hash; /* Containing all server_id for one domain_id */
|
|
/* The most recent entry in the hash. */
|
|
rpl_gtid *last_gtid;
|
|
/* Counter to allocate next seq_no for this domain. */
|
|
uint64 seq_no_counter;
|
|
|
|
int update_element(const rpl_gtid *gtid);
|
|
};
|
|
|
|
/* Mapping from domain_id to collection of elements. */
|
|
HASH hash;
|
|
my_bool initialized;
|
|
|
|
rpl_binlog_state_base() : initialized(0) {}
|
|
~rpl_binlog_state_base();
|
|
void init();
|
|
void reset_nolock();
|
|
void free();
|
|
bool load_nolock(struct rpl_gtid *list, uint32 count);
|
|
bool load_nolock(rpl_binlog_state_base *orig_state);
|
|
int update_nolock(const struct rpl_gtid *gtid);
|
|
int alloc_element_nolock(const rpl_gtid *gtid);
|
|
uint32 count_nolock();
|
|
int get_gtid_list_nolock(rpl_gtid *gtid_list, uint32 list_size);
|
|
rpl_gtid *find_nolock(uint32 domain_id, uint32 server_id);
|
|
bool is_before_pos(slave_connection_state *pos);
|
|
|
|
/*
|
|
Inline iterator over a binlog state, most recent GTID comes last for each
|
|
domain just like get_gtid_list_nolock().
|
|
|
|
The ITERATOR_FUNC should have signature bool f(const rpl_gtid *), and
|
|
return true in case of error (in which case iterate() aborts and also
|
|
returns true).
|
|
|
|
Intended to do custom GTID state processing without requiring the overhead
|
|
of an intermediate list, and where the extra code generation is justified.
|
|
*/
|
|
template <typename F> bool iterate(F iterator_func)
|
|
{
|
|
uint32 i, j;
|
|
ulong outer_records= hash.records;
|
|
|
|
for (i= 0; i < outer_records; ++i)
|
|
{
|
|
element *e= (element *)my_hash_element(&hash, i);
|
|
ulong inner_records= e->hash.records;
|
|
const rpl_gtid *last_gtid= e->last_gtid;
|
|
if (unlikely(!last_gtid))
|
|
{
|
|
DBUG_ASSERT(inner_records==0);
|
|
continue;
|
|
}
|
|
for (j= 0; j <= inner_records; ++j)
|
|
{
|
|
const rpl_gtid *gtid;
|
|
if (j < inner_records)
|
|
{
|
|
gtid= (rpl_gtid *)my_hash_element(&e->hash, j);
|
|
if (gtid == last_gtid)
|
|
continue;
|
|
}
|
|
else
|
|
gtid= e->last_gtid;
|
|
if (iterator_func(gtid))
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false; // No error
|
|
}
|
|
};
|
|
|
|
|
|
#endif /* RPL_GTID_BASE_H */
|