1.GTID_SET正常生成涉及到的堆棧信息
-do_command(THD*)
--dispatch_command(THD*,COM_DATA const*,enum_server_command)
---mysql_parse(THD*,Parser_state*)
----mysql_execute_command(THD*,bool)
-----trans_commit_stmt(THD*,bool)
------ha_commit_trans(THD*,bool,bool)
-------MYSQL_BIN_LOG::commit(THD*,bool)
--------MYSQL_BIN_LOG::ordered_commit(THD*,bool,bool)
---------MYSQL_BIN_LOG::process_commit_stage_queue(THD*,THD*)
----------Gtid_state::update_commit_group(THD*)
-----------Gtid_state::update_gtids_impl_own_gtid(THD*,bool)
------------Gtid_set::_add_gtid(Gtid const&)
-------------Gtid_set::_add_gtid(int,long long)
--------------Gtid_set::add_gno_interval(Interval_iterator *ivitp, rpl_gno start,rpl_gno end, Free_intervals_lock *lock)
1.1 GNO
/// Type of GNO, the second (numeric) component of GTID
typedef long long int rpl_gno;
1.2 Gtid_set::_add_gtid函數
void_add_gtid(rpl_sidnosidno,rpl_gnogno) {
add_gno_interval(&ivit, gno, gno +1, &lock);
}
1.3Gtid_set::add_gno_interval函數
voidGtid_set::add_gno_interval(Interval_iterator*ivitp,rpl_gnostart,
rpl_gnoend,Free_intervals_lock*lock) {
while((iv = ivit.get()) !=NULL) {
iv->start= start;
if(iv->end< end) iv->end= end;
*ivitp = ivit;
}
}
2.GTID_SET異常處理涉及到的堆棧信息
-Gtid_set::add_gno_interval(Interval_iterator *ivitp, rpl_gno start,rpl_gno end, Free_intervals_lock *lock)
--Gtid_set::get_free_interval(Interval **out)
---Gtid_set::create_new_chunk(int size)
----Gtid_set::add_interval_memory_lock_taken(int n_ivs,Interval *ivs)
2.1結構體Interval_chunk
/*
Contains a list of intervals allocated by this Gtid_set. When a
method of this class needs a new interval and there are no more
free intervals, a new Interval_chunk is allocated and the
intervals of it are added to the list of free intervals.
*/
struct Interval_chunk {
Interval_chunk *next;
Interval intervals[1];
};
2.2 Gtid_set::add_gno_interval關於GTID_SET異常處理部分
void Gtid_set::add_gno_interval(Interval_iterator*ivitp,rpl_gnostart,
rpl_gnoend,Free_intervals_lock*lock) {
/*
We come here if the interval cannot be combined with any existing
interval: it is after the previous interval (if any) and before
the current interval (if any). So we allocate a new interval and
insert it at the current position.
*/
Interval*new_iv;
lock->lock_if_not_locked();
get_free_interval(&new_iv);
new_iv->start= start;
new_iv->end= end;
ivit.insert(new_iv);
*ivitp = ivit;
DBUG_VOID_RETURN;
}
2.3 Gtid_set::get_free_interval函數
void Gtid_set::get_free_interval(Interval**out) {
if(ivit.get() ==NULL|| simulate_failure)create_new_chunk(CHUNK_GROW_SIZE)
}
2.4Gtid_set::create_new_chunk函數
void Gtid_set::create_new_chunk(int size) {
/*
Try to allocate the new chunk in MAX_NEW_CHUNK_ALLOCATE_TRIES
tries when encountering 'out of memory' situation.
*/
while (i < MAX_NEW_CHUNK_ALLOCATE_TRIES) {
/*
Allocate the new chunk. one element is already pre-allocated, so
we only add size-1 elements to the size of the struct.
*/
new_chunk = (Interval_chunk*)my_malloc(
key_memory_Gtid_set_Interval_chunk,
sizeof(Interval_chunk) +sizeof(Interval) * (size -1),MYF(MY_WME));
}
}
// add the intervals in the chunk to the list of free intervals
add_interval_memory_lock_taken(size, new_chunk->intervals);
}
2.5 Gtid_set::add_interval_memory_lock_taken函數
void Gtid_set::add_interval_memory_lock_taken(intn_ivs,Interval*ivs) {
// make ivs a linked list
for(inti =0; i < n_ivs -1; i++) ivs[i].next= &(ivs[i +1]);
Interval_iterator ivit(this);
ivs[n_ivs -1].next= ivit.get();
// add intervals to list of free intervals
ivit.set(&(ivs[0]));
}
3結論
以上是GTID_SET正常生成以及異常後重新生成的方式堆棧信息,歡迎各位指正!
附圖:斷點調試截圖