zoukankan      html  css  js  c++  java
  • MySQL ddl丢表

     

     

    MySQL ddl丢表:

      MySQL server层为了和innodb层保持数据一致性,在写binlog和redo log时,引入了两阶段提交,但不同的变更产生的日志并非都使用这种策略。

    下面就来看看ddl语句产生的binlog日志写入交互过程,从源码的角度理解大家熟知的MySQL ddl丢表。

      

    测试:   

      create table mm(id int primary key, name varchar(100));

    注意:测试在MySQL的5.5.18版本。因为dll语句默认提交,所以环境变量autocommit,tx_isolation不影响。

    步骤:

    1. 解析SQL语句

      HA_CREATE_INFO create_info(lex->create_info);

      Alter_info alter_info(lex->alter_info, thd->mem_root);

    生成ddl语句需要的数据结构。

    注意:在这个过程中,ddl语句进行了隐式提交
        if (trans_commit_implicit(thd)):  隐式提交
          thd->mdl_context.release_transactional_locks();  释放mdl锁

    2. innodb创建表

      函数:mysql_create_table_no_lock:
        调用innodb引擎的创建表结构,具体步骤此次省略,我们的重点主要是binlog写入的交互

    3. server写入binlog 

      1. 生成binlog日志

        write_bin_log

          THD::binlog_query 
            Query_log_event qinfo(this, query_arg, query_len, is_trans, direct,suppress_use, errcode);
            
    ddl产生的mysql binlog event的类型是Query_log_event

      2. 写入binlog cache

        file= &log_file; 使用mysql_bin_log全局的IO_CACHE.

        mysql_mutex_lock(&LOCK_log)
        event_info->write(file)
          Query_log_event::write
          
    根据event的内容,按照小端字节法,写入buff内存中,然后flush到mysql_bin_log对应的io_cache中。

      3. 同步日志

        binlog写入完成后,使用flush_and_sync,持久化到binlog文件中,最后释放lock_log.
          mysql_file_sync
            mysql_mutex_unlock(&LOCK_log);

    最后的结果是:
      

    复制代码
    mysql> show binlog events in 'binlog.000013';
    
    +---------------+-----+-------------+-----------+-------------+------------------------------------------------------------------------+
    | Log_name      | Pos | Event_type  | Server_id | End_log_pos | Info                                                                   |
    +---------------+-----+-------------+-----------+-------------+------------------------------------------------------------------------+
    | binlog.000013 |   4 | Format_desc |       100 |         107 | Server ver: 5.5.18.....................................................|
    | binlog.000013 | 107 | Query       |       100 |         228 | use `xpchild`; create table mm(id int primary key , name varchar(100)) |
    复制代码

    了解了上面的函数调用过程,下面我们模拟一下丢表的情形:

      

    在第二步结束后,kill mysqld模拟mysql crash的情形,然后重启,就会看到:

        show tables:显示存在表 mm
        show binlog:没有create table mm的query event出现。

    这样,主库和备库就在不一致的状态。

    思考:为什么ddl不使用事务性语句的binlog写入策略?因为ddl默认不需要commit,无法介入到两阶段?


    后记:除了ddl产生的不一致的问题,MySQL的字典表,因为没有使用事务引擎来存储,也会出现数据不一致的情况。
        不过,最近有消息传MySQL有意使用innodb引擎来保存字典表。

  • 相关阅读:
    zoj 3279 线段树 OR 树状数组
    fzu 1962 树状数组 OR 线段树
    hdu 5057 块状链表
    hdu3487 Play with Chain
    bzoj 1588营业额统计(HNOI 2002)
    poj2823 Sliding Window
    poj2828 Buy Tickets
    poj2395 Out of Hay
    poj3667 Hotel
    poj1703 Lost Cows
  • 原文地址:https://www.cnblogs.com/zengkefu/p/5678339.html
Copyright © 2011-2022 走看看