Quelle rpl_rli.h
Sprache: C
/* Copyright (c) 2005, 2017, Oracle and/or its affiliates.
Copyright ( c ) 2009 , 2017 , MariaDB Corporation
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_RLI_H
#define RPL_RLI_H
#include "rpl_relay_log_info_file.h"
#include "rpl_tblmap.h"
#include "rpl_reporting.h"
#include "rpl_utility.h"
#include "log.h" /* LOG_INFO, MYSQL_BIN_LOG */
#include "sql_class.h" /* THD */
#include "log_event.h"
#include "rpl_parallel.h"
struct RPL_TABLE_LIST;
class Master_info;
class Rpl_filter;
/****************************************************************************
Replication SQL Thread
Relay_log_info contains :
- the current relay log
- the current relay log offset
- master log name
- master log sequence corresponding to the last update
- misc information specific to the SQL thread
Relay_log_info is initialized from the slave . info file if such
exists . Otherwise , data members are intialized with defaults . The
initialization is done with Relay_log_info : : init ( ) call .
The format of slave . info file :
relay_log_name
relay_log_pos
master_log_name
master_log_pos
To clean up , call end_relay_log_info ( )
*****************************************************************************/
struct rpl_group_info;
struct inuse_relaylog;
class Relay_log_info:
public Relay_log_info_file, public Slave_reporting_capability
{
public :
/**
Flags for the state of reading the relay log . Note that these are
bit masks .
*/
enum enum_state_flag {
/** We are inside a group of events forming a statement */
IN_STMT=1 ,
/** We have inside a transaction */
IN_TRANSACTION=2
};
/*
The SQL thread owns one Relay_log_info , and each client that has
executed a BINLOG statement owns one Relay_log_info . This function
returns zero for the Relay_log_info object that belongs to the SQL
thread and nonzero for Relay_log_info objects that belong to
clients .
*/
inline bool belongs_to_client()
{
DBUG_ASSERT(sql_driver_thd);
return !sql_driver_thd->slave_thread;
}
/*
If true , events with the same server id should be replicated . This
field is set on creation of a relay log info structure by copying
the value of : : replicate_same_server_id and can be overridden if
necessary . For example of when this is done , check sql_binlog . cc ,
where the BINLOG statement can be used to execute " raw " events .
*/
bool replicate_same_server_id;
/*** The following variables can only be read when protect by data lock ****/
/*
info_fd - file descriptor of the info file . set only during
initialization or clean up - safe to read anytime
cur_log_fd - file descriptor of the current read relay log
*/
File info_fd,cur_log_fd;
/*
Protected with internal locks .
Must get data_lock when resetting the logs .
*/
MYSQL_BIN_LOG relay_log;
LOG_INFO linfo;
/*
cur_log
Pointer that either points at relay_log . get_log_file ( ) or
& rli - > cache_buf , depending on whether the log is hot or there was
the need to open a cold relay_log .
cache_buf
IO_CACHE used when opening cold relay logs .
*/
IO_CACHE cache_buf,*cur_log;
/*
Keeps track of the number of transactions that commits
before fsyncing . The option - - sync - relay - log - info determines
how many transactions should commit before fsyncing .
*/
uint sync_counter;
/*
Identifies when the recovery process is going on .
See sql / slave . cc : init_recovery for further details .
*/
bool is_relay_log_recovery;
/* The following variables are safe to read any time */
/* IO_CACHE of the info file - set only during init or end */
IO_CACHE &info_file= Info_file::file;
/*
List of temporary tables used by this connection .
This is updated when a temporary table is created or dropped by
a replication thread .
Not reset when replication ends , to allow one to access the tables
when replication restarts .
Protected by data_lock .
*/
All_tmp_tables_list *save_temporary_tables;
/*
standard lock acquisition order to avoid deadlocks :
run_lock , data_lock , relay_log . LOCK_log , relay_log . LOCK_index
*/
mysql_mutex_t data_lock, run_lock;
/*
start_cond is broadcast when SQL thread is started
stop_cond - when stopped
data_cond - when data protected by data_lock changes
*/
mysql_cond_t start_cond, stop_cond, data_cond;
/* parent Master_info structure */
Master_info *mi;
/*
List of active relay log files .
( This can be more than one in case of parallel replication ) .
*/
inuse_relaylog *inuse_relaylog_list;
inuse_relaylog *last_inuse_relaylog;
/*
Needed to deal properly with cur_log getting closed and re - opened with
a different log under our feet
*/
uint32 cur_log_old_open_count;
/*
If on init_info ( ) call error_on_rli_init_info is true that means
that previous call to init_info ( ) terminated with an error , RESET
SLAVE must be executed and the problem fixed manually .
*/
bool error_on_rli_init_info;
/*
Let ' s call a group ( of events ) :
- a transaction
or
- an autocommiting query + its associated events ( INSERT_ID ,
TIMESTAMP . . . )
We need these rli coordinates :
- relay log name and position of the beginning of the group we currently
are executing . Needed to know where we have to restart when replication has
stopped in the middle of a group ( which has been rolled back by the slave ) .
- relay log name and position just after the event we have just
executed . This event is part of the current group .
Formerly we only had the immediately above coordinates , plus a ' pending '
variable , but this dealt wrong with the case of a transaction starting on a
relay log and finishing ( commiting ) on another relay log . Case which can
happen when , for example , the relay log gets rotated because of
max_binlog_size .
Note : group_relay_log_name , group_relay_log_pos must only be
written from the thread owning the Relay_log_info ( SQL thread if
! belongs_to_client ( ) ; client thread executing BINLOG statement if
belongs_to_client ( ) ) .
*/
char (&group_relay_log_name)[FN_REFLEN]= relay_log_file.buf;
my_off_t &group_relay_log_pos= relay_log_pos.value;
char event_relay_log_name[FN_REFLEN];
ulonglong event_relay_log_pos;
ulonglong future_event_relay_log_pos;
/*
The master log name for current event . Only used in parallel replication .
*/
char future_event_master_log_name[FN_REFLEN];
/*
Original log name and position of the group we ' re currently executing
( whose coordinates are group_relay_log_name / pos in the relay log )
in the master ' s binlog . These concern the * group * , because in the master ' s
binlog the log_pos that comes with each event is the position of the
beginning of the group .
Note : group_master_log_name , group_master_log_pos must only be
written from the thread owning the Relay_log_info ( SQL thread if
! belongs_to_client ( ) ; client thread executing BINLOG statement if
belongs_to_client ( ) ) .
*/
char (&group_master_log_name)[FN_REFLEN]= read_master_log_file.buf;
my_off_t &group_master_log_pos= read_master_log_pos.value;
/*
Handling of the relay_log_space_limit optional constraint .
ignore_log_space_limit is used to resolve a deadlock between I / O and SQL
threads , the SQL thread sets it to unblock the I / O thread and make it
temporarily forget about the constraint .
*/
ulonglong log_space_limit;
Atomic_counter<uint64> log_space_total;
bool ignore_log_space_limit;
/*
Used by the SQL thread to instructs the IO thread to rotate
the logs when the SQL thread needs to purge to release some
disk space .
*/
bool sql_force_rotate_relay;
/*
The SQL driver thread sets this true while it is waiting at the end of the
relay log for more events to arrive . SHOW SLAVE STATUS uses this to report
Seconds_Behind_Master as zero while the SQL thread is so waiting .
*/
bool sql_thread_caught_up;
/**
Simple setter for @ ref worker_threads_caught_up ;
sets it ` false ` to indicate new user events in queue
@ pre @ ref data_lock held to prevent race with is_threads_caught_up ( )
*/
inline void unset_worker_threads_caught_up()
{
mysql_mutex_assert_owner(&data_lock);
worker_threads_caught_up= false ;
}
/**
@ return
` true ` if both @ ref sql_thread_caught_up and ( refresh according to
@ ref last_inuse_relaylog as needed ) @ ref worker_threads_caught_up
@ pre Only meaningful if ` mi - > using_parallel ( ) `
@ pre @ ref data_lock held to prevent race condition
@ note
Parallel replication requires the idleness of the main SQL thread as well ,
because after the thread sets its state to " busy " with ` data_lock ` held ,
it enqueues events * without this lock * . Not to mention any event the main
thread processes itself without distribution , e . g . , ignored ones .
*/
bool are_sql_threads_caught_up();
/* Last executed timestamp */
my_time_t last_master_timestamp;
/*
Latest when + exec_time read from the master ( by io_thread ) .
0 if there has been no new update events since the slave started .
*/
time_t newest_master_timestamp;
/*
When + exec_time of the last committed event on the slave .
In case of delayed slave and slave_timestamp is not set
then set to when + exec_time - 1 of the first seen event .
*/
time_t slave_timestamp;
void clear_until_condition();
/**
Reset the delay .
This is used by RESET SLAVE to clear the delay .
*/
void clear_sql_delay()
{
sql_delay= 0 ;
}
/*
Needed for problems when slave stops and we want to restart it
skipping one or more events in the master log that have caused
errors , and have been manually applied by DBA already .
Must be ulong as it ' s referred to from set_var . cc
*/
volatile ulonglong slave_skip_counter;
ulonglong max_relay_log_size;
volatile ulong abort_pos_wait; /* Incremented on change master */
volatile ulong slave_run_id; /* Incremented on slave start */
mysql_mutex_t log_space_lock;
mysql_cond_t log_space_cond;
/*
THD for the main sql thread , the one that starts threads to process
slave requests . If there is only one thread , then this THD is also
used for SQL processing .
A kill sent to this THD will kill the replication .
*/
THD *sql_driver_thd;
#ifndef DBUG_OFF
int events_till_abort;
#endif
enum_gtid_skip_type gtid_skip_flag;
/*
inited changes its value within LOCK_active_mi - guarded critical
sections at times of start_slave_threads ( ) ( 0 - > 1 ) and end_slave ( ) ( 1 - > 0 ) .
Readers may not acquire the mutex while they realize potential concurrency
issue .
If not set , the value of other members of the structure are undefined .
*/
volatile bool inited;
volatile bool abort_slave;
volatile bool stop_for_until;
volatile uint slave_running;
/*
Condition and its parameters from START SLAVE UNTIL clause .
UNTIL condition is tested with is_until_satisfied ( ) method that is
called by exec_relay_log_event ( ) . is_until_satisfied ( ) caches the result
of the comparison of log names because log names don ' t change very often ;
this cache is invalidated by parts of code which change log names with
notify_ * _ log_name_updated ( ) methods . ( They need to be called only if SQL
thread is running ) .
*/
enum {
UNTIL_NONE= 0 , UNTIL_MASTER_POS, UNTIL_RELAY_POS, UNTIL_GTID
} until_condition;
char until_log_name[FN_REFLEN];
ulonglong until_log_pos;
/* extension extracted from log_name and converted to int */
ulong until_log_name_extension;
/*
Cached result of comparison of until_log_name and current log name
- 2 means unitialised , - 1 , 0 , 1 are comarison results
*/
enum
{
UNTIL_LOG_NAMES_CMP_UNKNOWN= -2 , UNTIL_LOG_NAMES_CMP_LESS= -1 ,
UNTIL_LOG_NAMES_CMP_EQUAL= 0 , UNTIL_LOG_NAMES_CMP_GREATER= 1
} until_log_names_cmp_result;
/* Condition for UNTIL master_gtid_pos. */
slave_connection_state until_gtid_pos;
bool is_until_before_gtids;
/*
retried_trans is a cumulative counter : how many times the slave
has retried a transaction ( any ) since slave started .
Protected by data_lock .
*/
ulong retried_trans;
/*
Number of executed events for SLAVE STATUS .
Protected by slave_executed_entries_lock
*/
Atomic_counter<uint32_t> executed_entries;
/*
If the end of the hot relay log is made of master ' s events ignored by the
slave I / O thread , these two keep track of the coords ( in the master ' s
binlog ) of the last of these events seen by the slave I / O thread . If not ,
ign_master_log_name_end [ 0 ] = = 0 .
As they are like a Rotate event read / written from / to the relay log , they
are both protected by rli - > relay_log . LOCK_log .
*/
char ign_master_log_name_end[FN_REFLEN];
ulonglong ign_master_log_pos_end;
/* Similar for ignored GTID events. */
slave_connection_state ign_gtids;
/*
Identifies where the SQL Thread should create temporary files for the
LOAD DATA INFILE . This is used for security reasons .
*/
char slave_patternload_file[FN_REFLEN];
size_t slave_patternload_file_size;
rpl_parallel parallel;
/*
The relay_log_state keeps track of the current binlog state of the
execution of the relay log . This is used to know where to resume
current GTID position if the slave thread is stopped and
restarted . It is only accessed from the SQL thread , so it does
not need any locking .
*/
rpl_binlog_state relay_log_state;
/*
The restart_gtid_state is used when the SQL thread restarts on a relay log
in GTID mode . In multi - domain parallel replication , each domain may have a
separate position , so some events in more progressed domains may need to be
skipped . This keeps track of the domains that have not yet reached their
starting event .
*/
slave_connection_state restart_gtid_pos;
Relay_log_info(bool is_slave_recovery, const char * thread_name= "SQL" );
~Relay_log_info();
/*
Invalidate cached until_log_name and group_relay_log_name comparison
result . Should be called after any update of group_relay_log_name if
there chances that sql_thread is running .
*/
inline void notify_group_relay_log_name_update()
{
if (until_condition==UNTIL_RELAY_POS)
until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_UNKNOWN;
}
/*
The same as previous but for group_master_log_name .
*/
inline void notify_group_master_log_name_update()
{
if (until_condition==UNTIL_MASTER_POS)
until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_UNKNOWN;
}
void inc_group_relay_log_pos(ulonglong log_pos,
rpl_group_info *rgi,
bool skip_lock=0 );
int wait_for_pos(THD* thd, String* log_name, longlong log_pos,
longlong timeout);
void close_temporary_tables();
/* Check if UNTIL condition is satisfied. See slave.cc for more. */
bool is_until_satisfied(Log_event *ev);
inline ulonglong until_pos()
{
DBUG_ASSERT(until_condition == UNTIL_MASTER_POS ||
until_condition == UNTIL_RELAY_POS);
return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_pos :
group_relay_log_pos);
}
inline char *until_name()
{
DBUG_ASSERT(until_condition == UNTIL_MASTER_POS ||
until_condition == UNTIL_RELAY_POS);
return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_name :
group_relay_log_name);
}
/**
Helper function to do after statement completion .
This function is called from an event to complete the group by
either stepping the group position , if the " statement " is not
inside a transaction ; or increase the event position , if the
" statement " is inside a transaction .
@ param event_log_pos
Master log position of the event . The position is recorded in the
relay log info and used to produce information for < code > SHOW
SLAVE STATUS < / code > .
*/
bool stmt_done(my_off_t event_log_pos, THD *thd, rpl_group_info *rgi);
int alloc_inuse_relaylog(const char *name);
void free_inuse_relaylog(inuse_relaylog *ir);
void reset_inuse_relaylog();
int update_relay_log_state(rpl_gtid *gtid_list, uint32 count);
/**
Is the replication inside a group ?
The reader of the relay log is inside a group if either :
- The IN_TRANSACTION flag is set , meaning we ' re inside a transaction
- The IN_STMT flag is set , meaning we have read at least one row from
a multi - event entry .
This flag reflects the state of the log ' just now ' , ie after the last
read event would be executed .
This allow us to test if we can stop replication before reading
the next entry .
@ retval true Replication thread is currently inside a group
@ retval false Replication thread is currently not inside a group
*/
bool is_in_group() const {
return (m_flags & (IN_STMT | IN_TRANSACTION));
}
/**
Set the value of a replication state flag .
@ param flag Flag to set
*/
void set_flag(enum_state_flag flag)
{
m_flags|= flag;
}
/**
Get the value of a replication state flag .
@ param flag Flag to get value of
@ return @ c true if the flag was set , @ c false otherwise .
*/
bool get_flag(enum_state_flag flag)
{
return m_flags & flag;
}
/**
Clear the value of a replication state flag .
@ param flag Flag to clear
*/
void clear_flag(enum_state_flag flag)
{
m_flags&= ~flag;
}
bool flush();
/**
Reads the relay_log . info file .
*/
int init(const char * info_filename);
/**
Indicate that a delay starts .
This does not actually sleep ; it only sets the state of this
Relay_log_info object to delaying so that the correct state can be
reported by SHOW SLAVE STATUS and SHOW PROCESSLIST .
Requires rli - > data_lock .
@ param delay_end The time when the delay shall end .
*/
void start_sql_delay(time_t delay_end)
{
mysql_mutex_assert_owner(&data_lock);
sql_delay_end= delay_end;
THD_STAGE_INFO(sql_driver_thd, stage_sql_thd_waiting_until_delay);
}
int32 get_sql_delay() { return sql_delay; }
void set_sql_delay(int32 _sql_delay) { sql_delay= _sql_delay; }
time_t get_sql_delay_end() { return sql_delay_end; }
rpl_gtid last_seen_gtid;
ulong last_trans_retry_count;
private :
/**
Delay slave SQL thread by this amount , compared to master ( in
seconds ) . This is set with CHANGE MASTER TO MASTER_DELAY = X .
Guarded by data_lock . Initialized by the client thread executing
START SLAVE . Written by client threads executing CHANGE MASTER TO
MASTER_DELAY = X . Read by SQL thread and by client threads
executing SHOW SLAVE STATUS . Note : must not be written while the
slave SQL thread is running , since the SQL thread reads it without
a lock when executing Relay_log_info : : flush ( ) .
*/
uint32_t &sql_delay= Relay_log_info_file::sql_delay.value;
/**
During a delay , specifies the point in time when the delay ends .
This is used for the SQL_Remaining_Delay column in SHOW SLAVE STATUS .
Guarded by data_lock . Written by the sql thread . Read by client
threads executing SHOW SLAVE STATUS .
This is calculated as :
clock_time_for_event_on_master + clock_difference_between_master_and_slave +
SQL_DELAY .
*/
time_t sql_delay_end;
/*
Before the MASTER_DELAY parameter was added ( WL # 344 ) ,
relay_log . info had 4 lines . Now it has 5 lines .
*/
static const int LINES_IN_RELAY_LOG_INFO_WITH_DELAY= 5 ;
/*
Hint for when to stop event distribution by sql driver thread .
The flag is set ON by a non - group event when this event is in the middle
of a group ( e . g a transaction group ) so it ' s too early
to refresh the current - relay - log vs until - log cached comparison result .
And it is checked and to decide whether it ' s a right time to do so
when the being processed group has been fully scheduled .
*/
bool until_relay_log_names_defer;
/*
Holds the state of the data in the relay log .
We need this to ensure that we are not in the middle of a
statement or inside BEGIN . . . COMMIT when should rotate the
relay log .
*/
uint32 m_flags;
/**
When ` true ` , this worker threads ' copy of @ ref sql_thread_caught_up
represents that _ _ every__ worker thread is waiting for new events .
* The SQL driver thread sets this to ` false ` through
unset_worker_threads_caught_up ( ) as it prepares an event
( either to enqueue a worker or , e . g . , ignored events , process itself )
* For the main driver or any worker thread to refresh this state immediately
when it finishes , the procedure would have to be a critical section .
To avoid depending on a mutex , this state instead only returns to ` true `
as part of its reader , are_worker_threads_caught_up ( ) .
` Seconds_Behind_Master ` of SHOW SLAVE STATUS uses this method ( which also
reads ` sql_thread_caught_up ` ) to know when all SQL threads are waiting .
@ pre Only meaningful if ` mi - > using_parallel ( ) `
*/
bool worker_threads_caught_up= true ;
};
/*
In parallel replication , if we need to re - try a transaction due to a
deadlock or other temporary error , we may need to go back and re - read events
out of an earlier relay log .
This structure keeps track of the relaylogs that are potentially in use .
Each rpl_group_info has a pointer to one of those , corresponding to the
first GTID event .
A pair of reference count keeps track of how long a relay log is potentially
in use . When the ` completed ' flag is set , all events have been read out of
the relay log , but the log might still be needed for retry in worker
threads . As worker threads complete an event group , they increment
atomically the ` dequeued_count ' with number of events queued . Thus , when
completed is set and dequeued_count equals queued_count , the relay log file
is finally done with and can be purged .
By separating the queued and dequeued count , only the dequeued_count needs
multi - thread synchronisation ; the completed flag and queued_count fields
are only accessed by the SQL driver thread and need no synchronisation .
*/
struct inuse_relaylog {
inuse_relaylog *next;
Relay_log_info *rli;
/*
relay_log_state holds the binlog state corresponding to the start of this
relay log file . It is an array with relay_log_state_count elements .
*/
rpl_gtid *relay_log_state;
uint32 relay_log_state_count;
/* Number of events in this relay log queued for worker threads. */
Atomic_counter<int64> queued_count;
/* Number of events completed by worker threads. */
Atomic_counter<int64> dequeued_count;
/* Set when all events have been read from a relaylog. */
bool completed;
char name[FN_REFLEN];
inuse_relaylog(Relay_log_info *rli_arg, rpl_gtid *relay_log_state_arg,
uint32 relay_log_state_count_arg,
const char *name_arg):
next(0 ), rli(rli_arg), relay_log_state(relay_log_state_arg),
relay_log_state_count(relay_log_state_count_arg), queued_count(0 ),
dequeued_count(0 ), completed(false )
{
strmake_buf(name, name_arg);
}
};
enum start_alter_state
{
INVALID= 0 ,
REGISTERED, // Start Alter exist, Default state
COMMIT_ALTER, // COMMIT the alter
ROLLBACK_ALTER, // Rollback the alter
COMPLETED // COMMIT/ROLLBACK Alter written in binlog
};
struct start_alter_info
{
/*
ALTER id is defined as a pair of GTID ' s seq_no and domain_id .
*/
decltype(rpl_gtid::seq_no) sa_seq_no; // key for searching (SA's id)
uint32 domain_id;
bool direct_commit_alter; // when true CA thread executes the whole query
/*
0 prepared and not error from commit and rollback
> 0 error expected in commit / rollback
Rollback can be logged with 0 error if master is killed
*/
uint error;
enum start_alter_state state;
/* We are not using mysql_cond_t because we do not need PSI */
mysql_cond_t start_alter_cond;
};
struct Rpl_table_data
{
const table_def *tabledef;
TABLE *conv_table;
const Copy_field *copy_fields;
const Copy_field *copy_fields_end;
Rpl_table_data(const RPL_TABLE_LIST &rpl_table_list)
{
tabledef= &rpl_table_list.m_tabledef;
conv_table= rpl_table_list.m_conv_table;
copy_fields= rpl_table_list.m_online_alter_copy_fields;
copy_fields_end= rpl_table_list.m_online_alter_copy_fields_end;
}
bool is_online_alter() const { return copy_fields != NULL; }
};
/*
This is data for various state needed to be kept for the processing of
one event group ( transaction ) during replication .
In single - threaded replication , there will be one global rpl_group_info and
one global Relay_log_info per master connection . They will be linked
together .
In parallel replication , there will be one rpl_group_info object for
each running sql thread , each having their own thd .
All rpl_group_info will share the same Relay_log_info .
*/
struct rpl_group_info
{
rpl_group_info *next; /* For free list in rpl_parallel_thread */
Relay_log_info *rli;
THD *thd;
/*
Current GTID being processed .
The sub_id gives the binlog order within one domain_id . A zero sub_id
means that there is no active GTID .
*/
uint64 gtid_sub_id;
rpl_gtid current_gtid;
/* Currently applied event or NULL */
Log_event *current_event;
uint64 commit_id;
/*
This is used to keep transaction commit order .
We will signal this when we commit , and can register it to wait for the
commit_orderer of the previous commit to signal us .
*/
wait_for_commit commit_orderer;
/*
If non - zero , the sub_id of a prior event group whose commit we have to wait
for before committing ourselves . Then wait_commit_group_info points to the
event group to wait for .
Before using this , rpl_parallel_entry : : last_committed_sub_id should be
compared against wait_commit_sub_id . Only if last_committed_sub_id is
smaller than wait_commit_sub_id must the wait be done ( otherwise the
waited - for transaction is already committed , so we would otherwise wait
for the wrong commit ) .
*/
uint64 wait_commit_sub_id;
rpl_group_info *wait_commit_group_info;
/*
This holds a pointer to a struct that keeps track of the need to wait
for the previous batch of event groups to reach the commit stage , before
this batch can start to execute .
( When we execute in parallel the transactions that group committed
together on the master , we still need to wait for any prior transactions
to have reached the commit stage ) .
The pointed - to gco is only valid for as long as
gtid_sub_id < parallel_entry - > last_committed_sub_id . After that , it can
be freed by another thread .
*/
group_commit_orderer *gco;
struct rpl_parallel_entry *parallel_entry;
/*
A container to hold on Intvar - , Rand - , Uservar - log - events in case
the slave is configured with table filtering rules .
The withhold events are executed when their parent Query destiny is
determined for execution as well .
*/
Deferred_log_events *deferred_events;
/*
State of the container : true stands for IRU events gathering ,
false does for execution , either deferred or direct .
*/
bool deferred_events_collecting;
Annotate_rows_log_event *m_annotate_event;
RPL_TABLE_LIST *tables_to_lock; /* RBR: Tables to lock */
uint tables_to_lock_count; /* RBR: Count of tables to lock */
table_mapping m_table_map; /* RBR: Mapping table-id to table */
mysql_mutex_t sleep_lock;
mysql_cond_t sleep_cond;
/*
trans_retries varies between 0 to slave_transaction_retries and counts how
many times the slave has retried the present transaction ; gets reset to 0
when the transaction finally succeeds .
*/
ulong trans_retries;
/*
Used to defer stopping the SQL thread to give it a chance
to finish up the current group of events .
The timestamp is set and reset in @ c sql_slave_killed ( ) .
*/
time_t last_event_start_time;
char *event_relay_log_name;
char event_relay_log_name_buf[FN_REFLEN];
ulonglong event_relay_log_pos;
ulonglong future_event_relay_log_pos;
/*
The master log name for current event . Only used in parallel replication .
*/
char future_event_master_log_name[FN_REFLEN];
bool is_parallel_exec;
/* When gtid_pending is true, we have not yet done record_gtid(). */
bool gtid_pending;
int worker_error;
/*
Set true when we signalled that we reach the commit phase . Used to avoid
counting one event group twice .
*/
bool did_mark_start_commit;
/* Copy of flags2 from GTID event. */
uchar gtid_ev_flags2;
/* Copy of flags3 from GTID event. */
uint16 gtid_ev_flags_extra;
uint64 gtid_ev_sa_seq_no;
enum {
GTID_DUPLICATE_NULL=0 ,
GTID_DUPLICATE_IGNORE=1 ,
GTID_DUPLICATE_OWNER=2
};
/*
When - - gtid - ignore - duplicates , this is set to one of the above three
values :
GTID_DUPLICATE_NULL - Not using - - gtid - ignore - duplicates .
GTID_DUPLICATE_IGNORE - This gtid already applied , skip the event group .
GTID_DUPLICATE_OWNER - We are the current owner of the domain , and must
apply the event group and then release the domain .
*/
uint8 gtid_ignore_duplicate_state;
/*
Runtime state for printing a note when slave is taking
too long while processing a row event .
*/
longlong row_stmt_start_timestamp;
bool long_find_row_note_printed;
/* Needs room for "Gtid D-S-N\x00". */
mutable char gtid_info_buf[5 +10 +1 +10 +1 +20 +1 ];
/*
The timestamp , from the master , of the commit event .
Used to do delayed update of rli - > last_master_timestamp , for getting
reasonable values out of Seconds_Behind_Master in SHOW SLAVE STATUS .
*/
my_time_t last_master_timestamp;
/*
The exec_time of the transaction from the master ' s binlog . It is used with
log_slave_updates to preserve execution time value from the master when
re - binlogging on the slave .
*/
my_time_t orig_exec_time;
/*
Information to be able to re - try an event group in case of a deadlock or
other temporary error .
*/
inuse_relaylog *relay_log;
uint64 retry_start_offset;
uint64 retry_event_count;
/*
If ` speculation ' is ! = SPECULATE_NO , then we are optimistically running
this transaction in parallel , even though it might not be safe ( there may
be a conflict with a prior event group ) .
In this case , a conflict can cause other errors than deadlocks ( like
duplicate key for example ) . So in case of _ any_ error , we need to roll
back and retry the event group .
*/
enum enum_speculation {
/*
This transaction was group - committed together on the master with the
other transactions with which it is replicated in parallel .
*/
SPECULATE_NO,
/*
We will optimistically try to run this transaction in parallel with
other transactions , even though it is not known to be conflict free .
If we get a conflict , we will detect it as a deadlock , roll back and
retry .
*/
SPECULATE_OPTIMISTIC,
/*
This transaction got a conflict during speculative parallel apply , or
it was marked on the master as likely to cause a conflict or unsafe to
speculate . So it will wait for the prior transaction to commit before
starting to replicate .
*/
SPECULATE_WAIT
} speculation;
enum enum_retry_killed {
RETRY_KILL_NONE = 0 ,
RETRY_KILL_PENDING,
RETRY_KILL_KILLED
};
uchar killed_for_retry;
bool reserved_start_alter_thread;
bool finish_event_group_called;
/*
Used for two phase alter table
*/
rpl_parallel_thread *rpt;
Query_log_event *start_alter_ev;
bool direct_commit_alter;
start_alter_info *sa_info;
bool is_new_trans; // marker of start_new_trans context
/*
Use the scope of an RGI to re - assemble partial row log events into the
original rows log event . That is , the re - assembly and execution of a row
event happens happens in Partial_rows_log_event : : do_apply_event ( ) , so then
regardless of if the slave is running on parallel or serial mode , the
logic remains the same .
*/
Rows_log_event_assembler *assembler;
rpl_group_info(Relay_log_info *rli_);
~rpl_group_info();
void reinit(Relay_log_info *rli);
/*
Returns true if the argument event resides in the container ;
more specifically , the checking is done against the last added event .
*/
bool is_deferred_event(Log_event * ev)
{
return deferred_events_collecting ? deferred_events->is_last(ev) : false ;
};
/* The general cleanup that slave applier may need at the end of query. */
inline void cleanup_after_query()
{
if (deferred_events)
deferred_events->rewind();
};
/* The general cleanup that slave applier may need at the end of session. */
void cleanup_after_session()
{
if (deferred_events)
{
delete deferred_events;
deferred_events= NULL;
}
};
/**
Save pointer to Annotate_rows event and switch on the
binlog_annotate_row_events for this sql thread .
To be called when sql thread receives an Annotate_rows event .
*/
inline void set_annotate_event(Annotate_rows_log_event *event)
{
DBUG_ASSERT(m_annotate_event == NULL);
m_annotate_event= event;
this ->thd->variables.binlog_annotate_row_events= 1 ;
}
/**
Returns pointer to the saved Annotate_rows event or NULL if there is
no saved event .
*/
inline Annotate_rows_log_event* get_annotate_event()
{
return m_annotate_event;
}
/**
Delete saved Annotate_rows event ( if any ) and switch off the
binlog_annotate_row_events for this sql thread .
To be called when sql thread has applied the last ( i . e . with
STMT_END_F flag ) rbr event .
*/
inline void free_annotate_event()
{
if (m_annotate_event)
{
this ->thd->variables.binlog_annotate_row_events= 0 ;
delete m_annotate_event;
m_annotate_event= 0 ;
}
}
RPL_TABLE_LIST *get_table_data(TABLE *table_arg)
{
for (RPL_TABLE_LIST *ptr= tables_to_lock ; ptr ;
ptr= (RPL_TABLE_LIST*) ptr->next_global)
if (ptr->table == table_arg)
return ptr;
return (RPL_TABLE_LIST*) 0 ;
}
void clear_tables_to_lock();
void cleanup_context(THD *, bool , bool keep_domain_owner= false );
void slave_close_thread_tables(THD *);
void mark_start_commit_no_lock();
void mark_start_commit();
char *gtid_info() const ;
void unmark_start_commit();
longlong get_row_stmt_start_timestamp()
{
return row_stmt_start_timestamp;
}
void set_row_stmt_start_timestamp()
{
if (row_stmt_start_timestamp == 0 )
row_stmt_start_timestamp= microsecond_interval_timer();
}
void reset_row_stmt_start_timestamp()
{
row_stmt_start_timestamp= 0 ;
}
void set_long_find_row_note_printed()
{
long_find_row_note_printed= true ;
}
void unset_long_find_row_note_printed()
{
long_find_row_note_printed= false ;
}
bool is_long_find_row_note_printed()
{
return long_find_row_note_printed;
}
inline void inc_event_relay_log_pos()
{
if (!is_parallel_exec)
rli->event_relay_log_pos= future_event_relay_log_pos;
}
void finish_start_alter_event_group();
bool get_finish_event_group_called()
{
return finish_event_group_called;
}
void set_finish_event_group_called(bool value)
{
finish_event_group_called= value;
}
};
/**
The function
@ return true when the slave applier context is normal
false when either no slave applier around or
the applier is executing start_new_trans
*/
inline bool not_new_trans(rpl_group_info* rgi)
{
return rgi && !rgi->is_new_trans;
}
/**
The following functions for start_new_trans ' ctor and dtor .
*/
inline void mark_in_new_trans(rpl_group_info* rgi)
{
if (rgi)
rgi->is_new_trans= true ;
}
inline void unmark_in_new_trans(rpl_group_info* rgi)
{
if (rgi)
rgi->is_new_trans= false ;
}
/*
The class rpl_sql_thread_info is the THD : : system_thread_info for an SQL
thread ; this is either the driver SQL thread or a worker thread for parallel
replication .
*/
class rpl_sql_thread_info
{
public :
char cached_charset[6 ];
Rpl_filter* rpl_filter;
rpl_sql_thread_info(Rpl_filter *filter);
/*
Last charset ( 6 bytes ) seen by slave SQL thread is cached here ; it helps
the thread save 3 get_charset ( ) per Query_log_event if the charset is not
changing from event to event ( common situation ) .
When the 6 bytes are equal to 0 is used to mean " cache is invalidated " .
*/
void cached_charset_invalidate();
bool cached_charset_compare(char *charset) const ;
};
extern struct rpl_slave_state *rpl_global_gtid_slave_state;
extern gtid_waiting rpl_global_gtid_waiting;
int rpl_load_gtid_slave_state(THD *thd);
int find_gtid_slave_pos_tables(THD *thd);
int event_group_new_gtid(rpl_group_info *rgi, Gtid_log_event *gev);
void delete_or_keep_event_post_apply(rpl_group_info *rgi,
Log_event_type typ, Log_event *ev);
#endif /* RPL_RLI_H */
Messung V0.5 in Prozent C=90 H=100 G=95
¤ Dauer der Verarbeitung: 0.48 Sekunden
(vorverarbeitet am 2026-10-08)
¤
*© Formatika GbR, Deutschland
2026-10-09
Neuigkeiten
Aktuelles
Motto des Tages
Open Source Software
Jenseits des Üblichen ....
Besucherstatistik
Statistik
#Sources=1126438
#Domains=1867298