• 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引擎来保存字典表。


    下篇将介绍下事务性dml语句的日志写入策略。

  • 相关阅读:
    阿里云 NAS OSS 云盘价格对比 GB/小时
    kubernetes/k8s pod下多容器的设计模式(ambassador 大使代理模式,adapter 适配模式,sidecar 边车模式, init containers初始化容器)
    ❤️ 从125ms到11ms,记一次关键字检测过滤服务的优化 -python and Pythonnet
    高效的的关键字查找和检测(哈希表和Trie前缀树和FastCheck)在实际使用中的性能
    FastAPI 中的Async (并发和async/await)
    阿里云vs华为云 的容器镜像服务swr使用体验
    Supermap IClient3D 加载3DTiles倾斜摄影数据
    C#根据数据生成力引导图
    Android WebView
    Nginx 反向代理地址后,session丢失,不能登录的问题
  • 原文地址:https://www.cnblogs.com/xpchild/p/3802521.html
Copyright © 2020-2023  润新知