探索MYSQL源代码-BINLOG里的时间

今天在代码的时候无意中看到

void Item_func_now_local::store_now_in_TIME(MYSQL_TIME *now_time)
{
  THD *thd= current_thd;
  thd->variables.time_zone->gmt_sec_to_TIME(now_time,
                                             (my_time_t)thd->query_start());
  thd->time_zone_used= 1;
}

tem_func_sysdate_local::store_now_in_TIME(MYSQL_TIME *now_time)
{
  THD *thd= current_thd;
  thd->variables.time_zone->gmt_sec_to_TIME(now_time, (my_time_t) my_time(0));
  thd->time_zone_used= 1;
}

可以看到now()函数取的是这个语句执行开始时的时间

inline time_t query_start() { query_start_used=1; return start_time; }

而sysdate取得是执行到这个函数点的时间。

time_t my_time(myf flags __attribute__((unused)))
{
.....
  while ((t= time(0)) == (time_t) -1)
.....
}

所以就有了这个现象(当然别设置–sysdate-is-now )

mysql> select sysdate(), sleep(3), sysdate();
+---------------------+----------+---------------------+
| sysdate()           | sleep(3) | sysdate()           |
+---------------------+----------+---------------------+
| 2011-03-07 15:02:48 |        0 | 2011-03-07 15:02:51 |
+---------------------+----------+---------------------+

基于statement replication,源端的now(), sysdate() 等函数都是原封不动的传递到对端。
对端应用binlog的时候,sysdate()自然就会使用本地的时间,所以用sysdate()除了检测slave lag,没有别的用处, 还容易误用。

那么now() 是如何保证与源节点的时间一样呢?

通过mysqlbinlog可看到大量的set timestamp 语句。
每个event group 的最开始都会使用set timestamp来决定这次查询的开始点,而这个设置影响到group内的now()。

我们来看看set timestamp 的函数实现,从sql/sql_yacc.yy 的关键字set:出发,跳到sql/sql_parse.cc
的sql_set_variables, 再来到sql/set_var.cc的实现类

bool sys_var_timestamp::update(THD *thd,  set_var *var)
{
  thd->set_time((time_t) var->save_result.ulonglong_value);
  return 0;
}

转到set_time的实现sql/sql_class.h

class THD :public Statement,
           public Open_tables_state
{
.......
  inline void   set_time(time_t t)
  {
    start_time= user_time= t;
........

可以看到set timestamp 就是修改start_time, 而从上面的now()可以看到,now()取的就是start_time。
replication就是依靠存储在event里的set timestamp 来保证now函数的时间一致的。

ps: sysdate函数应该是源自于Oracle, dataguard是基于data block,进入block之前sysdate已经计算出写入,所以不存在这个问题。

 

觉得文章有用?立即: 和朋友一起 共学习 共进步!

猜您喜欢

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>