Chinaunix首页 | 论坛 | 博客
  • 博客访问: 52437
  • 博文数量: 6
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 70
  • 用 户 组: 普通用户
  • 注册时间: 2011-05-15 19:11
文章分类

全部博文(6)

文章存档

2015年(6)

我的朋友

分类: Mysql/postgreSQL

2015-04-24 17:19:29

源码阅读推荐工具:
vim + ctag + cscope + ycm+ indexer+nerdtree+taglist
详细使用请google

编译源码的时候首先需要开启HAVE_REPLICATION宏定义
在执行 start slave命令后,mysql会执行sql_parse 中SQLCOM_SLAVE_START分支
res= start_slave(thd, active_mi, 1 /* net report*/);
slave 从这个函数开始执行,5.6中这个函数在rpl_slave.cc中
函数传人三个参数,第一个参数定义了线程描述符,每个客户端都有一个线程处理,在
这个地方还负责创建slave复制线程(IO)和延迟插入线程(Sql)
第二个参数主要是主库信息,供slave 线程从主库dump binlog使用
第三个参数 
int start_slave(THD* thd , Master_info* mi, bool net_report) {
 
  if (global_init_info(mi, false, thread_mask))
 
  else if (server_id_supplied && *mi->host)
   lave_errno = start_slave_threads(false/
}

global_init_info来初始化主库信息,start_slave_threads会先启动io 线程,io线程启动无误启动sql 线程
最后terminate_slave_threads确保io,sql同时启动
int start_slave_threads(bool need_lock_slave, bool wait_for_start,
  Master_info* mi, int thread_mask)
{
if (thread_mask & SLAVE_IO)
start_slave_thread(…handle_slave_io..)
if (!error && (thread_mask & SLAVE_SQL))
start_slave_thread(….handle_slave_sql…)
if (error)
   terminate_slave_threads(mi, thread_mask & SLAVE_IO, need_lock_slave);
}
handle_slave_io  handle_slave_sql为线程处理函数,下面先看一下io读写线程,发现mysql
的io是只起了一个线程来做这个事情,应该是为了保持binlog event的时序性
pthread_handler_t handle_slave_io(void *arg)
{
if (RUN_HOOK(binlog_relay_io, thread_start, (thd, mi)))
}
rpl_handler.h中展开宏RUN_HOOK:
#define RUN_HOOK(group, hook, args) \
(group ##_delegate->is_empty() ? \
 group ##_delegate->hook args)
发现调用了binlog_relay_io_delegate->thread_start(thd, mi)
int Binlog_relay_IO_delegate::thread_start(THD *thd, Master_info *mi)
{
init_param(¶m, mi);
FOREACH_OBSERVER(ret, thread_start, thd, (¶m));
}
init_param主要是为了初始化参数(主库的用户名,密码,binlog文件名,binlog读取的偏移量),展开宏
#define FOREACH_OBSERVER(r, f, thd, args) \
Observer_info_iterator iter= observer_info_iter(); \
Observer_info *info= iter++; \
for (; info; info= iter++) \
{ \
if (((Observer *)info->observer)->f \
  && ((Observer *)info->observer)->f args) \
} \

到这里就很清楚了,此处用了观察者模式,最终回调typedef Binlog_relay_IO_observer Observer;
的thread_start,初始化的时候Binlog_relay_IO_observer是以插件的形式通过register_binlog_relay_io_observer函数注册到观察者list里面,所以最终实现io的功能是在plugin/semisync实现。
从补丁目录找到下面的结构体,所以上面分析的thread_start 函数其实是指向repl_semi_slave_io_start
的函数指针,至此mysql slave io hook启动。
Binlog_relay_IO_observer relay_io_observer = {
sizeof(Binlog_relay_IO_observer), // len

repl_semi_slave_io_start, // start
repl_semi_slave_io_end, // stop
repl_semi_slave_request_dump, // request_transmit
repl_semi_slave_read_event, // after_read_event
repl_semi_slave_queue_event, // after_queue_event
repl_semi_reset_slave, // reset
};

阅读(2485) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~