MySQL 8.0.39
Source Code Documentation
Gtid_state Class Reference

Represents the server's GTID state: the set of committed GTIDs, the set of lost gtids, the set of owned gtids, the owner of each owned gtid, and a Mutex_cond_array that protects updates to gtids of each SIDNO. More...

#include <rpl_gtid.h>

Public Member Functions

 Gtid_state (Checkable_rwlock *_sid_lock, Sid_map *_sid_map)
 Constructs a new Gtid_state object. More...
 
int init ()
 Add @GLOBAL.SERVER_UUID to this binlog's Sid_map. More...
 
int clear (THD *thd)
 Reset the state and persistor after RESET MASTER: remove all logged and lost gtids, but keep owned gtids as they are. More...
 
bool is_executed (const Gtid &gtid) const
 Returns true if the given GTID is logged. More...
 
bool is_owned (const Gtid &gtid) const
 Returns true if GTID is owned, otherwise returns 0. More...
 
enum_return_status acquire_ownership (THD *thd, const Gtid &gtid)
 Acquires ownership of the given GTID, on behalf of the given thread. More...
 
void update_commit_group (THD *first_thd)
 This function updates both the THD and the Gtid_state to reflect that the transaction set of transactions has ended, and it does this for the whole commit group (by following the thd->next_to_commit pointer). More...
 
void update_on_commit (THD *thd)
 Remove the GTID owned by thread from owned GTIDs, stating that thd->owned_gtid was committed. More...
 
void update_on_rollback (THD *thd)
 Update the state after the given thread has rollbacked. More...
 
void acquire_anonymous_ownership ()
 Acquire anonymous ownership. More...
 
void release_anonymous_ownership ()
 Release anonymous ownership. More...
 
int32 get_anonymous_ownership_count ()
 Return the number of clients that hold anonymous ownership. More...
 
void begin_automatic_gtid_violating_transaction ()
 Increase the global counter when starting a GTID-violating transaction having GTID_NEXT=AUTOMATIC. More...
 
void end_automatic_gtid_violating_transaction ()
 Decrease the global counter when ending a GTID-violating transaction having GTID_NEXT=AUTOMATIC. More...
 
int32 get_automatic_gtid_violating_transaction_count ()
 Return the number of ongoing GTID-violating transactions having GTID_NEXT=AUTOMATIC. More...
 
void begin_anonymous_gtid_violating_transaction ()
 Increase the global counter when starting a GTID-violating transaction having GTID_NEXT=ANONYMOUS. More...
 
void end_anonymous_gtid_violating_transaction ()
 Decrease the global counter when ending a GTID-violating transaction having GTID_NEXT=ANONYMOUS. More...
 
void end_gtid_violating_transaction (THD *thd)
 
int32 get_anonymous_gtid_violating_transaction_count ()
 Return the number of ongoing GTID-violating transactions having GTID_NEXT=AUTOMATIC. More...
 
void begin_gtid_wait ()
 Increase the global counter when starting a call to WAIT_FOR_EXECUTED_GTID_SET or WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS. More...
 
void end_gtid_wait ()
 Decrease the global counter when ending a call to WAIT_FOR_EXECUTED_GTID_SET or WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS. More...
 
int32 get_gtid_wait_count ()
 Return the number of clients that have an ongoing call to WAIT_FOR_EXECUTED_GTID_SET or WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS. More...
 
rpl_gno get_automatic_gno (rpl_sidno sidno) const
 Computes the next available GNO. More...
 
rpl_gno get_last_executed_gno (rpl_sidno sidno) const
 Return the last executed GNO for a given SIDNO, e.g. More...
 
enum_return_status generate_automatic_gtid (THD *thd, rpl_sidno specified_sidno=0, rpl_gno specified_gno=0, rpl_sidno *locked_sidno=nullptr)
 Generates the GTID (or ANONYMOUS, if GTID_MODE = OFF or OFF_PERMISSIVE) for the THD, and acquires ownership. More...
 
void lock_sidno (rpl_sidno sidno)
 Locks a mutex for the given SIDNO. More...
 
void unlock_sidno (rpl_sidno sidno)
 Unlocks a mutex for the given SIDNO. More...
 
void broadcast_sidno (rpl_sidno sidno)
 Broadcasts updates for the given SIDNO. More...
 
void assert_sidno_lock_owner (rpl_sidno sidno) const
 Assert that we own the given SIDNO. More...
 
bool wait_for_sidno (THD *thd, rpl_sidno sidno, struct timespec *abstime, bool update_thd_status=true)
 Wait for a signal on the given SIDNO. More...
 
bool wait_for_gtid (THD *thd, const Gtid &gtid, struct timespec *abstime=nullptr)
 This is only a shorthand for wait_for_sidno, which contains additional debug printouts and assertions for the case when the caller waits for one specific GTID. More...
 
bool wait_for_gtid_set (THD *thd, Gtid_set *gtid_set, double timeout, bool update_thd_status=true)
 Wait until the given Gtid_set is included in @GLOBAL.GTID_EXECUTED. More...
 
void lock_sidnos (const Gtid_set *set)
 Locks one mutex for each SIDNO where the given Gtid_set has at least one GTID. More...
 
void unlock_sidnos (const Gtid_set *set)
 Unlocks the mutex for each SIDNO where the given Gtid_set has at least one GTID. More...
 
void broadcast_sidnos (const Gtid_set *set)
 Broadcasts the condition variable for each SIDNO where the given Gtid_set has at least one GTID. More...
 
enum_return_status ensure_sidno ()
 Ensure that owned_gtids, executed_gtids, lost_gtids, gtids_only_in_table, previous_gtids_logged and sid_locks have room for at least as many SIDNOs as sid_map. More...
 
enum_return_status add_lost_gtids (Gtid_set *gtid_set, bool starts_with_plus)
 Adds the given Gtid_set to lost_gtids and executed_gtids. More...
 
void update_prev_gtids (Gtid_set *write_gtid_set)
 Updates previously logged GTID set before writing to table. More...
 
const Gtid_setget_lost_gtids () const
 Return a pointer to the Gtid_set that contains the lost gtids. More...
 
const Gtid_setget_executed_gtids () const
 
const Gtid_setget_gtids_only_in_table () const
 
const Gtid_setget_previous_gtids_logged () const
 
const Owned_gtidsget_owned_gtids () const
 Return a pointer to the Owned_gtids that contains the owned gtids. More...
 
rpl_sidno get_server_sidno () const
 Return the server's SID's SIDNO. More...
 
const rpl_sidget_server_sid () const
 Return the server's SID. More...
 
size_t get_max_string_length () const
 Debug only: Returns an upper bound on the length of the string generated by to_string(), not counting '\0'. More...
 
int to_string (char *buf) const
 Debug only: Generate a string in the given buffer and return the length. More...
 
char * to_string () const
 Debug only: return a newly allocated string, or NULL on out-of-memory. More...
 
void print () const
 Debug only: print this Gtid_state to stdout. More...
 
void dbug_print (const char *text="") const
 Print this Gtid_state to the trace file if debug is enabled; no-op otherwise. More...
 
int save (THD *thd)
 Save gtid owned by the thd into executed_gtids variable and gtid_executed table. More...
 
int save (const Gtid_set *gtid_set)
 Insert the gtid set into table. More...
 
int save_gtids_of_last_binlog_into_table ()
 Save the set of gtids logged in the last binlog into gtid_executed table. More...
 
int read_gtid_executed_from_table ()
 Fetch gtids from gtid_executed table and store them into gtid_executed set. More...
 
int compress (THD *thd)
 Compress the gtid_executed table, read each row by the PK(sid, gno_start) in increasing order, compress the first consecutive gtids range (delete consecutive gtids from the second consecutive gtid, then update the first gtid) within a single transaction. More...
 
int warn_or_err_on_modify_gtid_table (THD *thd, Table_ref *table)
 Push a warning to client if user is modifying the gtid_executed table explicitly by a non-XA transaction. More...
 

Private Member Functions

void update_gtids_impl (THD *thd, bool is_commit)
 Remove the GTID owned by thread from owned GTIDs. More...
 
void unlock_owned_sidnos (const THD *thd)
 Unlock all SIDNOs owned by the given THD. More...
 
void broadcast_owned_sidnos (const THD *thd)
 Broadcast the condition for all SIDNOs owned by the given THD. More...
 
bool update_gtids_impl_check_skip_gtid_rollback (THD *thd)
 Used by unit tests that need to access private members. More...
 
bool update_gtids_impl_do_nothing (THD *thd)
 This is a sub task of update_gtids_impl responsible only to handle the case of a thread that owns nothing and does not violate GTID consistency. More...
 
bool update_gtids_impl_begin (THD *thd)
 This is a sub task of update_gtids_impl responsible only to evaluate if the thread is committing in the middle of a statement by checking THD's is_commit_in_middle_of_statement flag. More...
 
void update_gtids_impl_own_gtid_set (THD *thd, bool is_commit)
 Handle the case that the thread own a set of GTIDs. More...
 
void update_gtids_impl_lock_sidno (rpl_sidno sidno)
 Lock a given sidno of a transaction being updated. More...
 
void update_gtids_impl_lock_sidnos (THD *thd)
 Locks the sidnos of all the GTIDs of the commit group starting on the transaction passed as parameter. More...
 
void update_gtids_impl_own_gtid (THD *thd, bool is_commit)
 Handle the case that the thread own a single non-anonymous GTID. More...
 
void update_gtids_impl_broadcast_and_unlock_sidno (rpl_sidno sidno)
 Unlock a given sidno after broadcasting its changes. More...
 
void update_gtids_impl_broadcast_and_unlock_sidnos ()
 Unlocks all locked sidnos after broadcasting their changes. More...
 
void update_gtids_impl_own_anonymous (THD *thd, bool *more_trx)
 Handle the case that the thread owns ANONYMOUS GTID. More...
 
void update_gtids_impl_own_nothing (THD *thd)
 Handle the case that the thread owns nothing. More...
 
void update_gtids_impl_end (THD *thd, bool more_trx)
 Handle the final part of update_gtids_impl. More...
 
enum_return_status ensure_commit_group_sidnos (rpl_sidno sidno)
 Ensure that commit_group_sidnos have room for the SIDNO passed as parameter. More...
 

Private Attributes

rpl_gno next_free_gno
 The next_free_gno variable will be set with the supposed next free GNO every time a new GNO is delivered automatically or when a transaction is rolled back, releasing a GNO smaller than the last one delivered. More...
 
Checkable_rwlocksid_lock
 Read-write lock that protects updates to the number of SIDs. More...
 
Sid_mapsid_map
 The Sid_map used by this Gtid_state. More...
 
Mutex_cond_array sid_locks
 Contains one mutex/cond pair for every SIDNO. More...
 
Gtid_set lost_gtids
 The set of GTIDs that existed in some previously purged binary log. More...
 
Gtid_set executed_gtids
 
Gtid_set gtids_only_in_table
 
Gtid_set previous_gtids_logged
 
Owned_gtids owned_gtids
 The set of GTIDs that are owned by some thread. More...
 
rpl_sidno server_sidno
 The SIDNO for this server. More...
 
std::atomic< int32atomic_anonymous_gtid_count {0}
 The number of anonymous transactions owned by any client. More...
 
std::atomic< int32atomic_automatic_gtid_violation_count {0}
 The number of GTID-violating transactions that use GTID_NEXT=AUTOMATIC. More...
 
std::atomic< int32atomic_anonymous_gtid_violation_count {0}
 The number of GTID-violating transactions that use GTID_NEXT=AUTOMATIC. More...
 
std::atomic< int32atomic_gtid_wait_count {0}
 The number of clients that are executing WAIT_FOR_EXECUTED_GTID_SET or WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS. More...
 
Prealloced_array< bool, 8 > commit_group_sidnos
 This array is used by Gtid_state_update_gtids_impl* functions. More...
 

Detailed Description

Represents the server's GTID state: the set of committed GTIDs, the set of lost gtids, the set of owned gtids, the owner of each owned gtid, and a Mutex_cond_array that protects updates to gtids of each SIDNO.

Locking:

This data structure has a read-write lock that protects the number of SIDNOs, and a Mutex_cond_array that contains one mutex per SIDNO. The rwlock is always the global_sid_lock.

Access methods generally assert that the caller already holds the appropriate lock:

  • before accessing any global data, hold at least the rdlock.
  • before accessing a specific SIDNO in a Gtid_set or Owned_gtids (e.g., calling Gtid_set::_add_gtid(Gtid)), hold either the rdlock and the SIDNO's mutex lock; or the wrlock. If you need to hold multiple mutexes, they must be acquired in order of increasing SIDNO.
  • before starting an operation that needs to access all SIDs (e.g. Gtid_set::to_string()), hold the wrlock.

The access type (read/write) does not matter; the write lock only implies that the entire data structure is locked whereas the read lock implies that everything except SID-specific data is locked.

Constructor & Destructor Documentation

◆ Gtid_state()

Gtid_state::Gtid_state ( Checkable_rwlock _sid_lock,
Sid_map _sid_map 
)
inline

Constructs a new Gtid_state object.

Parameters
_sid_lockRead-write lock that protects updates to the number of SIDs.
_sid_mapSid_map used by this Gtid_state.

Member Function Documentation

◆ acquire_anonymous_ownership()

void Gtid_state::acquire_anonymous_ownership ( )
inline

Acquire anonymous ownership.

The caller must hold either sid_lock.rdlock or sid_lock.wrlock. (The caller must have taken the lock and checked that gtid_mode!=ON before calling this function, or else the gtid_mode could have changed to ON by a concurrent SET GTID_MODE.)

◆ acquire_ownership()

enum_return_status Gtid_state::acquire_ownership ( THD thd,
const Gtid gtid 
)

Acquires ownership of the given GTID, on behalf of the given thread.

The caller must lock the SIDNO before invoking this function.

Parameters
thdThe thread that will own the GTID.
gtidThe Gtid to acquire ownership of.
Returns
RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.

◆ add_lost_gtids()

enum_return_status Gtid_state::add_lost_gtids ( Gtid_set gtid_set,
bool  starts_with_plus 
)

Adds the given Gtid_set to lost_gtids and executed_gtids.

lost_gtids must be a subset of executed_gtids. purged_gtid and executed_gtid sets are appended with the argument set provided the latter is disjoint with gtid_executed owned_gtids.

Requires that the caller holds global_sid_lock.wrlock.

Parameters
[in,out]gtid_setThe gtid_set to add. If the gtid_set does not start with a plus sign (starts_with_plus is false), @GLOBAL.GTID_PURGED will be removed from the gtid_set.
starts_with_plusIf true, the gtid_set passed is required to be disjoint from @GLOBAL.GTID_PURGED; if false, the gtid_set passed is required to be a superset of @GLOBAL.GTID_PURGED.
Returns
RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.

◆ assert_sidno_lock_owner()

void Gtid_state::assert_sidno_lock_owner ( rpl_sidno  sidno) const
inline

Assert that we own the given SIDNO.

◆ begin_anonymous_gtid_violating_transaction()

void Gtid_state::begin_anonymous_gtid_violating_transaction ( )
inline

Increase the global counter when starting a GTID-violating transaction having GTID_NEXT=ANONYMOUS.

◆ begin_automatic_gtid_violating_transaction()

void Gtid_state::begin_automatic_gtid_violating_transaction ( )
inline

Increase the global counter when starting a GTID-violating transaction having GTID_NEXT=AUTOMATIC.

◆ begin_gtid_wait()

void Gtid_state::begin_gtid_wait ( )
inline

Increase the global counter when starting a call to WAIT_FOR_EXECUTED_GTID_SET or WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS.

◆ broadcast_owned_sidnos()

void Gtid_state::broadcast_owned_sidnos ( const THD thd)
private

Broadcast the condition for all SIDNOs owned by the given THD.

◆ broadcast_sidno()

void Gtid_state::broadcast_sidno ( rpl_sidno  sidno)
inline

Broadcasts updates for the given SIDNO.

◆ broadcast_sidnos()

void Gtid_state::broadcast_sidnos ( const Gtid_set set)

Broadcasts the condition variable for each SIDNO where the given Gtid_set has at least one GTID.

◆ clear()

int Gtid_state::clear ( THD thd)

Reset the state and persistor after RESET MASTER: remove all logged and lost gtids, but keep owned gtids as they are.

The caller must hold the write lock on sid_lock before calling this function.

Parameters
thdThread requesting to reset the persistor
Return values
0Success
-1Error

◆ compress()

int Gtid_state::compress ( THD thd)

Compress the gtid_executed table, read each row by the PK(sid, gno_start) in increasing order, compress the first consecutive gtids range (delete consecutive gtids from the second consecutive gtid, then update the first gtid) within a single transaction.

Parameters
thdThread requesting to compress the table
Return values
0OK
1The table was not found.
-1Error

◆ dbug_print()

void Gtid_state::dbug_print ( const char *  text = "") const
inline

Print this Gtid_state to the trace file if debug is enabled; no-op otherwise.

◆ end_anonymous_gtid_violating_transaction()

void Gtid_state::end_anonymous_gtid_violating_transaction ( )
inline

Decrease the global counter when ending a GTID-violating transaction having GTID_NEXT=ANONYMOUS.

◆ end_automatic_gtid_violating_transaction()

void Gtid_state::end_automatic_gtid_violating_transaction ( )
inline

Decrease the global counter when ending a GTID-violating transaction having GTID_NEXT=AUTOMATIC.

◆ end_gtid_violating_transaction()

void Gtid_state::end_gtid_violating_transaction ( THD thd)

◆ end_gtid_wait()

void Gtid_state::end_gtid_wait ( )
inline

Decrease the global counter when ending a call to WAIT_FOR_EXECUTED_GTID_SET or WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS.

◆ ensure_commit_group_sidnos()

enum_return_status Gtid_state::ensure_commit_group_sidnos ( rpl_sidno  sidno)
private

Ensure that commit_group_sidnos have room for the SIDNO passed as parameter.

This function must only be called in one place: Gtid_state::ensure_sidno().

Parameters
sidnoThe SIDNO.
Returns
RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.

◆ ensure_sidno()

enum_return_status Gtid_state::ensure_sidno ( )

Ensure that owned_gtids, executed_gtids, lost_gtids, gtids_only_in_table, previous_gtids_logged and sid_locks have room for at least as many SIDNOs as sid_map.

This function must only be called in one place: Sid_map::add_sid().

Requires that the write lock on sid_locks is held. If any object needs to be resized, then the lock will be temporarily upgraded to a write lock and then degraded to a read lock again; there will be a short period when the lock is not held at all.

Returns
RETURN_STATUS_OK or RETURN_STATUS_REPORTED_ERROR.

◆ generate_automatic_gtid()

enum_return_status Gtid_state::generate_automatic_gtid ( THD thd,
rpl_sidno  specified_sidno = 0,
rpl_gno  specified_gno = 0,
rpl_sidno locked_sidno = nullptr 
)

Generates the GTID (or ANONYMOUS, if GTID_MODE = OFF or OFF_PERMISSIVE) for the THD, and acquires ownership.

Parameters
thdThe thread.
specified_sidnoExternally generated sidno.
specified_gnoExternally generated gno.
[in,out]locked_sidnoThis parameter should be used when there is a need of generating many GTIDs without having to acquire/release a sidno_lock many times. The caller must hold global_sid_lock and unlock the locked_sidno after invocation when locked_sidno > 0 if locked_sidno!=NULL. The caller must not hold global_sid_lock when locked_sidno==NULL. See comments on function code to more details.
Returns
RETURN_STATUS_OK or RETURN_STATUS_ERROR. Error can happen in case of out of memory or if the range of GNOs was exhausted.

◆ get_anonymous_gtid_violating_transaction_count()

int32 Gtid_state::get_anonymous_gtid_violating_transaction_count ( )
inline

Return the number of ongoing GTID-violating transactions having GTID_NEXT=AUTOMATIC.

◆ get_anonymous_ownership_count()

int32 Gtid_state::get_anonymous_ownership_count ( )
inline

Return the number of clients that hold anonymous ownership.

◆ get_automatic_gno()

rpl_gno Gtid_state::get_automatic_gno ( rpl_sidno  sidno) const

Computes the next available GNO.

Parameters
sidnoThe GTID's SIDNO.
Return values
-1The range of GNOs was exhausted (i.e., more than 1<<63-1 GTIDs with the same UUID have been generated).
>0The GNO for the GTID.

◆ get_automatic_gtid_violating_transaction_count()

int32 Gtid_state::get_automatic_gtid_violating_transaction_count ( )
inline

Return the number of ongoing GTID-violating transactions having GTID_NEXT=AUTOMATIC.

◆ get_executed_gtids()

const Gtid_set * Gtid_state::get_executed_gtids ( ) const
inline

◆ get_gtid_wait_count()

int32 Gtid_state::get_gtid_wait_count ( )
inline

Return the number of clients that have an ongoing call to WAIT_FOR_EXECUTED_GTID_SET or WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS.

◆ get_gtids_only_in_table()

const Gtid_set * Gtid_state::get_gtids_only_in_table ( ) const
inline

◆ get_last_executed_gno()

rpl_gno Gtid_state::get_last_executed_gno ( rpl_sidno  sidno) const

Return the last executed GNO for a given SIDNO, e.g.

for the following set: UUID:1-10, UUID:12, UUID:15-20 20 will be returned.

Parameters
sidnoThe GTID's SIDNO.
Return values
TheGNO or 0 if set is empty.

◆ get_lost_gtids()

const Gtid_set * Gtid_state::get_lost_gtids ( ) const
inline

Return a pointer to the Gtid_set that contains the lost gtids.

◆ get_max_string_length()

size_t Gtid_state::get_max_string_length ( ) const
inline

Debug only: Returns an upper bound on the length of the string generated by to_string(), not counting '\0'.

The actual length may be shorter.

◆ get_owned_gtids()

const Owned_gtids * Gtid_state::get_owned_gtids ( ) const
inline

Return a pointer to the Owned_gtids that contains the owned gtids.

◆ get_previous_gtids_logged()

const Gtid_set * Gtid_state::get_previous_gtids_logged ( ) const
inline

◆ get_server_sid()

const rpl_sid & Gtid_state::get_server_sid ( ) const
inline

Return the server's SID.

◆ get_server_sidno()

rpl_sidno Gtid_state::get_server_sidno ( ) const
inline

Return the server's SID's SIDNO.

◆ init()

int Gtid_state::init ( )

Add @GLOBAL.SERVER_UUID to this binlog's Sid_map.

This can't be done in the constructor because the constructor is invoked at server startup before SERVER_UUID is initialized.

The caller must hold the read lock or write lock on sid_locks before invoking this function.

Return values
0Success
1Error (out of memory or IO error).

◆ is_executed()

bool Gtid_state::is_executed ( const Gtid gtid) const
inline

Returns true if the given GTID is logged.

Parameters
gtidThe Gtid to check.
Return values
trueThe gtid is logged in the binary log.
falseThe gtid is not logged in the binary log.

◆ is_owned()

bool Gtid_state::is_owned ( const Gtid gtid) const
inline

Returns true if GTID is owned, otherwise returns 0.

Parameters
gtidThe Gtid to check.
Returns
true if some thread owns the gtid, false if the gtid is not owned

◆ lock_sidno()

void Gtid_state::lock_sidno ( rpl_sidno  sidno)
inline

Locks a mutex for the given SIDNO.

◆ lock_sidnos()

void Gtid_state::lock_sidnos ( const Gtid_set set)

Locks one mutex for each SIDNO where the given Gtid_set has at least one GTID.

Locks are acquired in order of increasing SIDNO.

◆ print()

void Gtid_state::print ( ) const
inline

Debug only: print this Gtid_state to stdout.

◆ read_gtid_executed_from_table()

int Gtid_state::read_gtid_executed_from_table ( )

Fetch gtids from gtid_executed table and store them into gtid_executed set.

Return values
0OK
1The table was not found.
-1Error

◆ release_anonymous_ownership()

void Gtid_state::release_anonymous_ownership ( )
inline

Release anonymous ownership.

◆ save() [1/2]

int Gtid_state::save ( const Gtid_set gtid_set)

Insert the gtid set into table.

Parameters
gtid_setcontains a set of gtid, which holds the sidno and the gno.
Return values
0OK
-1Error

◆ save() [2/2]

int Gtid_state::save ( THD thd)

Save gtid owned by the thd into executed_gtids variable and gtid_executed table.

Parameters
thdSession to commit
Return values
0OK
-1Error

◆ save_gtids_of_last_binlog_into_table()

int Gtid_state::save_gtids_of_last_binlog_into_table ( )

Save the set of gtids logged in the last binlog into gtid_executed table.

Return values
0OK
-1Error

◆ to_string() [1/2]

char * Gtid_state::to_string ( ) const
inline

Debug only: return a newly allocated string, or NULL on out-of-memory.

◆ to_string() [2/2]

int Gtid_state::to_string ( char *  buf) const
inline

Debug only: Generate a string in the given buffer and return the length.

◆ unlock_owned_sidnos()

void Gtid_state::unlock_owned_sidnos ( const THD thd)
private

Unlock all SIDNOs owned by the given THD.

◆ unlock_sidno()

void Gtid_state::unlock_sidno ( rpl_sidno  sidno)
inline

Unlocks a mutex for the given SIDNO.

◆ unlock_sidnos()

void Gtid_state::unlock_sidnos ( const Gtid_set set)

Unlocks the mutex for each SIDNO where the given Gtid_set has at least one GTID.

◆ update_commit_group()

void Gtid_state::update_commit_group ( THD first_thd)

This function updates both the THD and the Gtid_state to reflect that the transaction set of transactions has ended, and it does this for the whole commit group (by following the thd->next_to_commit pointer).

It will:

  • Clean up the thread state when a thread owned GTIDs is empty.
  • Release ownership of all GTIDs owned by the THDs. This removes the GTIDs from Owned_gtids and clears the ownership status in the THDs object.
  • Add the owned GTIDs to executed_gtids when the thread is committing.
  • Decrease counters of GTID-violating transactions.
  • Send a broadcast on the condition variable for every sidno for which we released ownership.
Parameters
first_thdThe first thread of the group commit that needs GTIDs to be updated.

◆ update_gtids_impl()

void Gtid_state::update_gtids_impl ( THD thd,
bool  is_commit 
)
private

Remove the GTID owned by thread from owned GTIDs.

This will:

  • Clean up the thread state if the thread owned GTIDs is empty.
  • Release ownership of all GTIDs owned by the THD. This removes the GTID from Owned_gtids and clears the ownership status in the THD object.
  • Add the owned GTID to executed_gtids if the is_commit flag is set.
  • Decrease counters of GTID-violating transactions.
  • Send a broadcast on the condition variable for every sidno for which we released ownership.
Parameters
[in]thdThread for which owned gtids are updated.
[in]is_commitIf true, the update is for a commit (not a rollback).

◆ update_gtids_impl_begin()

bool Gtid_state::update_gtids_impl_begin ( THD thd)
private

This is a sub task of update_gtids_impl responsible only to evaluate if the thread is committing in the middle of a statement by checking THD's is_commit_in_middle_of_statement flag.

This flag is true for anonymous transactions, when the 'transaction' has been split into multiple transactions in the binlog, and the present transaction is not the last one.

This means two things:

  • We should not release anonymous ownership in case gtid_next=anonymous. If we did, it would be possible for user to set GTID_MODE=ON from a concurrent transaction, making it impossible to commit the current transaction.
  • We should not decrease the counters for GTID-violating statements. If we did, it would be possible for a concurrent client to set ENFORCE_GTID_CONSISTENCY=ON despite there is an ongoing transaction that violates GTID consistency.

The flag is set in two cases:

  1. We are committing the statement cache when there are more changes in the transaction cache.

    This happens either because a single statement in the beginning of a transaction updates both transactional and non-transactional tables, or because we are committing a non-transactional update in the middle of a transaction when binlog_direct_non_transactional_updates=1.

    In this case, the flag is set further down in this function.

  2. The statement is one of the special statements that may generate multiple transactions: CREATE...SELECT, DROP TABLE, DROP DATABASE. See comment for THD::owned_gtid in sql/sql_class.h.

    In this case, the THD::is_commit_in_middle_of_statement flag is set by the caller and the flag becomes true here.

Parameters
[in]thd- Thread to be evaluated.
Returns
The value of thread's is_commit_in_middle_of_statement flag.

◆ update_gtids_impl_broadcast_and_unlock_sidno()

void Gtid_state::update_gtids_impl_broadcast_and_unlock_sidno ( rpl_sidno  sidno)
private

Unlock a given sidno after broadcasting its changes.

This is a sub task of update_gtids_impl responsible only to unlock the sidno of the GTID being updated after broadcasting its changes.

Parameters
[in]sidno- The sidno to be broadcasted and unlocked.

◆ update_gtids_impl_broadcast_and_unlock_sidnos()

void Gtid_state::update_gtids_impl_broadcast_and_unlock_sidnos ( )
private

Unlocks all locked sidnos after broadcasting their changes.

This is a sub task of update_commit_group responsible only to unlock the sidno(s) of the GTID(s) being updated after broadcasting their changes.

◆ update_gtids_impl_check_skip_gtid_rollback()

bool Gtid_state::update_gtids_impl_check_skip_gtid_rollback ( THD thd)
private

Used by unit tests that need to access private members.

This is a sub task of update_on_rollback responsible only to handle the case of a thread that needs to skip GTID operations when it has "failed to commit".

Administrative commands [CHECK|REPAIR|OPTIMIZE|ANALYZE] TABLE are written to the binary log even when they fail. When the commands fail, they will call update_on_rollback; later they will write the binary log. But we must not do any of the things in update_gtids_impl if we are going to write the binary log. So these statements set the skip_gtid_rollback flag, which tells update_on_rollback to return early. When the statements are written to the binary log they will call update_on_commit as usual.

Parameters
[in]thd- Thread to be evaluated.
Return values
trueThe transaction should skip the rollback, false otherwise.

◆ update_gtids_impl_do_nothing()

bool Gtid_state::update_gtids_impl_do_nothing ( THD thd)
private

This is a sub task of update_gtids_impl responsible only to handle the case of a thread that owns nothing and does not violate GTID consistency.

If the THD does not own anything, there is nothing to do, so we can do an early return of the update process. Except if there is a GTID consistency violation; then we need to decrease the counter, so then we can continue executing inside update_gtids_impl.

Parameters
[in]thd- Thread to be evaluated.
Return values
trueThe transaction can be skipped because it owns nothing and does not violate GTID consistency, false otherwise.

◆ update_gtids_impl_end()

void Gtid_state::update_gtids_impl_end ( THD thd,
bool  more_trx 
)
private

Handle the final part of update_gtids_impl.

This is a sub task of update_gtids_impl responsible only to handle the call to end_gtid_violating_transaction function when there is no more transactions split after the current transaction.

Parameters
[in]thd- Thread for which owned GTID is updated.
[in]more_trx- This is the value returned from Gtid_state::update_gtids_impl_begin and can be changed for transactions owning anonymous GTID at Gtid_state::update_gtids_impl_own_anonymous.

◆ update_gtids_impl_lock_sidno()

void Gtid_state::update_gtids_impl_lock_sidno ( rpl_sidno  sidno)
private

Lock a given sidno of a transaction being updated.

This is a sub task of update_gtids_impl responsible only to lock the sidno of the GTID being updated.

Parameters
[in]sidno- The sidno to be locked.

◆ update_gtids_impl_lock_sidnos()

void Gtid_state::update_gtids_impl_lock_sidnos ( THD thd)
private

Locks the sidnos of all the GTIDs of the commit group starting on the transaction passed as parameter.

This is a sub task of update_commit_group responsible only to lock the sidno(s) of the GTID(s) being updated.

The function should follow thd->next_to_commit to lock all sidnos of all transactions being updated in a group.

Parameters
[in]thd- Thread that owns the GTID(s) to be updated or leader of the commit group in the case of a commit group update.

◆ update_gtids_impl_own_anonymous()

void Gtid_state::update_gtids_impl_own_anonymous ( THD thd,
bool *  more_trx 
)
private

Handle the case that the thread owns ANONYMOUS GTID.

This is a sub task of update_gtids_impl responsible only to handle the case of a thread with an ANONYMOUS GTID being updated.

  • Release ownership of the anonymous GTID owned by the THD and clears the ownership status in the THD object.
  • Decrease counters of GTID-violating transactions.
Parameters
[in]thd- Thread to be updated that owns anonymous GTID.
[in,out]more_trx- If the 'transaction' has been split into multiple transactions in the binlog. This is firstly assigned with the return of Gtid_state::update_gtids_impl_begin function, and its value can be set to true when Gtid_state::update_gtids_impl_anonymous_gtid detects more content on the transaction cache.

◆ update_gtids_impl_own_gtid()

void Gtid_state::update_gtids_impl_own_gtid ( THD thd,
bool  is_commit 
)
private

Handle the case that the thread own a single non-anonymous GTID.

This is a sub task of update_gtids_impl responsible only to handle the case of a thread with a single non-anonymous GTID being updated either for commit or rollback.

  • Release ownership of the GTID owned by the THD. This removes the GTID from Owned_gtids and clears the ownership status in the THD object.
  • Add the owned GTID to executed_gtids if the is_commit flag is set.
  • Send a broadcast on the condition variable for the sidno which we released ownership.
Parameters
[in]thd- Thread to be updated that owns single non-anonymous GTID.
[in]is_commit- If the thread is being updated by a commit.

◆ update_gtids_impl_own_gtid_set()

void Gtid_state::update_gtids_impl_own_gtid_set ( THD thd,
bool  is_commit 
)
private

Handle the case that the thread own a set of GTIDs.

This is a sub task of update_gtids_impl responsible only to handle the case of a thread with a set of GTIDs being updated.

  • Release ownership of the GTIDs owned by the THD. This removes the GTID from Owned_gtids and clears the ownership status in the THD object.
  • Add the owned GTIDs to executed_gtids if the is_commit flag is set.
  • Send a broadcast on the condition variable for the sidno which we released ownership.
Parameters
[in]thd- Thread for which owned GTID set should be updated.
[in]is_commit- If the thread is being updated by a commit.

◆ update_gtids_impl_own_nothing()

void Gtid_state::update_gtids_impl_own_nothing ( THD thd)
private

Handle the case that the thread owns nothing.

This is a sub task of update_gtids_impl responsible only to handle the case of a thread that owns nothing being updated.

There are two cases when this happens:

  • Normally, it is a rollback of an automatic transaction, so the is_commit is false and gtid_next=automatic.
  • There is also a corner case. This case may happen for a transaction that uses GTID_NEXT=AUTOMATIC, and violates GTID_CONSISTENCY, and commits changes to the database, but does not write to the binary log, so that no GTID is generated. An example is CREATE TEMPORARY TABLE inside a transaction when binlog_format=row. Despite the thread does not own anything, the GTID consistency violation makes it necessary to call end_gtid_violating_transaction. Therefore MYSQL_BIN_LOG::gtid_end_transaction will call gtid_state->update_on_commit in this case, and subsequently we will reach this case.
Parameters
[in]thd- Thread to be updated that owns anonymous GTID.

◆ update_on_commit()

void Gtid_state::update_on_commit ( THD thd)

Remove the GTID owned by thread from owned GTIDs, stating that thd->owned_gtid was committed.

This will:

  • remove owned GTID from owned_gtids;
  • remove all owned GTIDS from thd->owned_gtid and thd->owned_gtid_set;
Parameters
thdThread for which owned gtids are updated.

◆ update_on_rollback()

void Gtid_state::update_on_rollback ( THD thd)

Update the state after the given thread has rollbacked.

This will:

  • release ownership of all GTIDs owned by the THD;
  • remove owned GTID from owned_gtids;
  • remove all owned GTIDS from thd->owned_gtid and thd->owned_gtid_set;
  • send a broadcast on the condition variable for every sidno for which we released ownership.
Parameters
thdThread for which owned gtids are updated.

◆ update_prev_gtids()

void Gtid_state::update_prev_gtids ( Gtid_set write_gtid_set)

Updates previously logged GTID set before writing to table.

◆ wait_for_gtid()

bool Gtid_state::wait_for_gtid ( THD thd,
const Gtid gtid,
struct timespec *  abstime = nullptr 
)

This is only a shorthand for wait_for_sidno, which contains additional debug printouts and assertions for the case when the caller waits for one specific GTID.

◆ wait_for_gtid_set()

bool Gtid_state::wait_for_gtid_set ( THD thd,
Gtid_set gtid_set,
double  timeout,
bool  update_thd_status = true 
)

Wait until the given Gtid_set is included in @GLOBAL.GTID_EXECUTED.

Parameters
thdThe calling thread.
gtid_setGtid_set to wait for.
[in]timeoutThe maximum number of milliseconds that the function should wait, or 0 to wait indefinitely.
[in]update_thd_statuswhen true updates the stage info with the new wait condition, when false keeps the current stage info.
Return values
falseSuccess.
trueFailure: either timeout or thread was killed. If thread was killed, the error has been generated.

◆ wait_for_sidno()

bool Gtid_state::wait_for_sidno ( THD thd,
rpl_sidno  sidno,
struct timespec *  abstime,
bool  update_thd_status = true 
)

Wait for a signal on the given SIDNO.

NOTE: This releases a lock!

This requires that the caller holds a read lock on sid_lock. It will release the lock before waiting; neither global_sid_lock nor the mutex lock on SIDNO will not be held when this function returns.

Parameters
thdTHD object of the caller.
sidnoSidno to wait for.
[in]abstimeThe absolute point in time when the wait times out and stops, or NULL to wait indefinitely.
[in]update_thd_statuswhen true updates the stage info with the new wait condition, when false keeps the current stage info.
Return values
falseSuccess.
trueFailure: either timeout or thread was killed. If thread was killed, the error has been generated.

◆ warn_or_err_on_modify_gtid_table()

int Gtid_state::warn_or_err_on_modify_gtid_table ( THD thd,
Table_ref table 
)

Push a warning to client if user is modifying the gtid_executed table explicitly by a non-XA transaction.

Push an error to client if user is modifying it explicitly by a XA transaction.

Parameters
thdThread requesting to access the table
tableThe table is being accessed.
Return values
0No warning or error was pushed to the client.
1Push a warning to client.
2Push an error to client.

Member Data Documentation

◆ atomic_anonymous_gtid_count

std::atomic<int32> Gtid_state::atomic_anonymous_gtid_count {0}
private

The number of anonymous transactions owned by any client.

◆ atomic_anonymous_gtid_violation_count

std::atomic<int32> Gtid_state::atomic_anonymous_gtid_violation_count {0}
private

The number of GTID-violating transactions that use GTID_NEXT=AUTOMATIC.

◆ atomic_automatic_gtid_violation_count

std::atomic<int32> Gtid_state::atomic_automatic_gtid_violation_count {0}
private

The number of GTID-violating transactions that use GTID_NEXT=AUTOMATIC.

◆ atomic_gtid_wait_count

std::atomic<int32> Gtid_state::atomic_gtid_wait_count {0}
private

The number of clients that are executing WAIT_FOR_EXECUTED_GTID_SET or WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS.

◆ commit_group_sidnos

Prealloced_array<bool, 8> Gtid_state::commit_group_sidnos
private

This array is used by Gtid_state_update_gtids_impl* functions.

The array items (one per sidno of the sid_map) will be set as true for each sidno that requires to be locked when updating a set of GTIDs (at Gtid_set::update_gtids_impl_lock_sidnos).

The array items will be set false at Gtid_set::update_gtids_impl_broadcast_and_unlock_sidnos.

It is used to so that lock, unlock, and broadcast operations are only called once per sidno per commit group, instead of once per transaction.

Its access is protected by:

  • global_sid_lock->wrlock when growing and cleaning up;
  • MYSQL_BIN_LOG::LOCK_commit when setting true/false on array items.

◆ executed_gtids

Gtid_set Gtid_state::executed_gtids
private

◆ gtids_only_in_table

Gtid_set Gtid_state::gtids_only_in_table
private

◆ lost_gtids

Gtid_set Gtid_state::lost_gtids
private

The set of GTIDs that existed in some previously purged binary log.

This is always a subset of executed_gtids.

◆ next_free_gno

rpl_gno Gtid_state::next_free_gno
private

The next_free_gno variable will be set with the supposed next free GNO every time a new GNO is delivered automatically or when a transaction is rolled back, releasing a GNO smaller than the last one delivered.

It was introduced in an optimization of Gtid_state::get_automatic_gno and Gtid_state::generate_automatic_gtid functions.

Locking scheme

This variable can be read and modified in four places:

  • During server startup, holding global_sid_lock.wrlock;
  • By a client thread holding global_sid_lock.wrlock (doing a RESET MASTER);
  • By a client thread calling MYSQL_BIN_LOG::write_transaction function (often the group commit FLUSH stage leader). It will call Gtid_state::generate_automatic_gtid, that will acquire global_sid_lock.rdlock and lock_sidno(get_server_sidno()) when getting a new automatically generated GTID;
  • By a client thread rolling back, holding global_sid_lock.rdlock and lock_sidno(get_server_sidno()).

◆ owned_gtids

Owned_gtids Gtid_state::owned_gtids
private

The set of GTIDs that are owned by some thread.

◆ previous_gtids_logged

Gtid_set Gtid_state::previous_gtids_logged
private

◆ server_sidno

rpl_sidno Gtid_state::server_sidno
private

The SIDNO for this server.

◆ sid_lock

Checkable_rwlock* Gtid_state::sid_lock
mutableprivate

Read-write lock that protects updates to the number of SIDs.

◆ sid_locks

Mutex_cond_array Gtid_state::sid_locks
private

Contains one mutex/cond pair for every SIDNO.

◆ sid_map

Sid_map* Gtid_state::sid_map
mutableprivate

The Sid_map used by this Gtid_state.


The documentation for this class was generated from the following files: