狠狠撸

狠狠撸Share a Scribd company logo
MySQL 源码分析 ——代码结构与基本流程 彭立勋 Alibaba DBA Team
Topics MySQL 基本架构 源码目录结构 核心类库与函数 主要模块 数据流
MySQL 基本架构
MySQL 目录结构 (1) BUILD :  内含在各个平台、各种编译器下进行编译的脚本。如 compile-pentium-debug 表示在 pentium 架构上进行调试编译的脚本。 client :  客户端工具,如 mysql,mysqladmin 之类。 cmd-line-utils : readline,libedit 工具。 config :  给 aclocal 使用的配置文件。 dbug :  提供一些调试用的宏定义。 Docs : MySQL 在不同平台下的参考手册 extra :  提供 innochecksum,resolveip 等额外的小工具。 include :  包含的头文件 libmysql :  库文件,生产 libmysqlclient.so 。 libmysql_r :  线程安全的库文件,生成 libmysqlclient_r.so 。 libmysqld :  嵌入式 MySQL Server 库 . libservices : 5.5.0 中新加的目录,实现了打印功能。
MySQL 目录结构 (2) man :  适合 man 命令查看的帮助文件。 mysql-test : mysqld 的测试工具套件。 mysys :  为实现跨平台, MySQL 自己实现了一套常用的数据结构和算法,如 string, hash 等。还包含一些底层函数的跨平台封装 , 一般以 my_ 开头。 netware :  在 netware 平台上进行编译时需要的工具和库。 plugin : MySQL 5.1 开始支持一个插件式 API 接口 , 不需要重启 mysqld 即可动态载入插件 ,FullText 就是一个例子。 pstack : GNU 异步栈追踪工具。 regex :  正则表达式实现 ( 来自多伦多大学 Henry Spencer 大牛的源码 ) 。 scripts :  提供脚本工具,如 mysql_install_db/mysqld_safe 等。 server-tools:   包含 instance_manager 子目录 , 负责实例的本地和远程管理。
MySQL 目录结构 (3) sql: MySQL Server 主要代码,将会生成 mysqld 文件。 sql-bench:  一些基准测试代码代码 , 主要是 Perl 程序 ( 虽然后缀是 sh) 。 sql-common:  存放部分服务器端和客户端都会用到的代码 , 有些地方的同名文件是这里 lin 过去的。 storage :  存储引擎所在目录。 strings : string 库 , 包含很多字符串处理的函数。 support-files : my.cnf 示例配置文件及编译所需的一些工具。 tests :  测试文件所在目录。 unittest :  单元测试文件。 vio :  虚拟 io 系统,是对 network io 的封装 , 把不同的协议封装成统一的 IO 函数。 win :  在 windows 平台编译所需的文件和一些说明。 zlib : zlib 算法库 (GNU)
InnoDB 目录结构 (1) btr: B+ 树的实现 buf :  缓冲池的实现 , 包括 LRU 算法 ,Flush 刷新算法等 dict : InnoDB 内存数据字典的实现 dyn : InnoDB 动态数组的实现 fil : InnoDB 文件数据结构以及对于文件的一些操作 fsp :  对 InnoDB 物理文件的管理 , 如页 / 区 / 段等 ( 即 File Space) ha :  哈希算法的实现 handler :  继承与 MySQL 的 handler, 实现 handler API 与 Server 交互 ibuf :  插入缓冲 (Insert Buffer) 的实现 include : InnoDB 所有头文件都放在这个目录 , 是查找结构定义的最佳地点 lock : InnoDB 的锁实现及三种锁算法实现 log:   日志缓冲 (Log Buffer) 和重做日志组 (Redo Log) 的实现
InnoDB 目录结构 (2) mem:  辅助缓冲池 (Additional Memory Pool) 的实现 , 用来申请一些内部数据结构的内存 mtr :  事务的底层实现 ( 日志 , 缓冲 ) os :  封装一些对于操作系统的操作 page :  页的实现 , 研究 InnoDB 文件结构 , 这个目录至关重要 pars :  重载部分 MySQL 的 SQL Parser( 有待商榷 ) que : Query graph, 基本上没啥用 read :  读取游标的实现 rem :  行管理操作 ( 比较操作 , 打印等 ) row :  对于各种类型行数据操作的实现 srv : InnoDB 后台线程 , 启动服务 ,Master Thread,SQL 队列等 sync : InnoDB 互斥变量 (Mutex) 的实现 , 基本同步机制 thr : InnoDB 封装的可移植线程库
InnoDB 目录结构 (3) trx :  事务的实现 usr : Session 管理 ut :  各种通用小工具
核心类库 THD :  线程类 Item : Item 类 ( 查询条目 , 函数 ,WHERE,ORDER,GROUP,ON 子句等 ) TABLE :  表描述符 TABEL_LIST : JOIN 操作描述符 Field :  列数据类型及属性定义 LEX :  语法树 Protocol :  通讯协议 NET :  网络描述符 handler :  存储引擎接口
核心函数库 (1) 内存操作 : init_alloc_root :  内存池初始化 , 生成内存池根 (MEM_ROOT) alloc_root :  申请内存池内存 , 从 mem_root 制定的内存池申请内存块 free_root :  释放内存池 , 通过 MyFlags 指定哪种内存可以被释放 文件操作 : my_open :  打开一个文件 my_close :  关闭一个文件 my_b_flush_io_cache :  讲数据从内存缓冲写到物理磁盘 end_io_cache :  释放一个 IO_CACHE 对象 哈希操作 : _ hash_init :  初始化 HASH 描述符 hash_search :  搜索哈希表 , 调用 hash_first hash_first :  返回哈希表中找到的第一个行指针 , 否则返回 0
核心函数库 (2) 字符串操作 : strappend : 填充字符串 strmov :  移动字符串到新地址
核心算法 Bitmaps  bitmap_init/bimap_free:  创建与释放一个位图  (8*n 个位为单位 ) bitmap_set_bit/bitmap_fast_test_and_set:  设置位图的一个位 bitmap_clear_all/bitmap_set_all:  清空或全部设置一个位图 bitmap_cmp:  对两个位图的特定位比较 Join Buffer 如果存在条件过滤 , 则第一次过滤完的记录将放入 Join Buffer, 避免第二次再判断 Sort Buffer 算法一 :  将排序字段和主键放入 Sort Buffer 排序 , 按照结果用主键取出数据返回 算法二 :  将整行数据放入 Sort Buffer, 排序完成后直接从 Sort Buffer 返回数据
MySQL 数据流
MySQL 启动流程 主要代码在 sql/mysqld.cc 中,精简后的代码如下: int main(int argc, char **argv) // 标准入口函数 MY_INIT(argv[0]);// 调用 mysys/My_init.c->my_init() ,初始化 mysql 内部的系统库 logger.init_base(); // 初始化日志功能 init_common_variables(MYSQL_CONFIG_NAME,argc, argv, load_default_groups) // 调用 load_defaults(conf_file_name, groups, &argc, &argv) ,读取配置信息 user_info = check_user(mysqld_user);// 检测启动时的用户选项 set_user(mysqld_user, user_info);// 设置以该用户运行 init_server_components();// 初始化内部的一些组件,如 table_cache, query_cache 等。 network_init();// 初始化网络模块,创建 socket 监听 start_signal_handler();//  创建 pid 文件 mysql_rm_tmp_tables() || acl_init(opt_noacl)// 删除 tmp_table 并初始化数据库级别的权限。 init_status_vars(); //  初始化 mysql 中的 status 变量 start_handle_manager();// 创建 manager 线程 handle_connections_sockets();// 主要处理函数,处理新的连接并创建新的线程处理
MySQL 监听连接 主要代码在 sql/mysqld.cc 中 (handle_connections_sockets) ,精简后的代码如下: pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) { FD_SET(unix_sock,&clientFDs); // unix_socket 在 network_init 中被打开 while (!abort_loop) { // abort_loop 是全局变量,在某些情况下被置为 1 表示要退出。 readFDs=clientFDs; //  需要监听的 socket select((int) max_used_connection,&readFDs,0,0,0); // select 异步 (? 科学家解释下是同步还是异步 ) 监听,当接收到 ?? 以后返回。 new_sock = accept(sock, my_reinterpret_cast(struct sockaddr *) (&cAddr),  &length); //  接受请求 thd= new THD; //  创建 mysqld 任务线程描述符,它封装了一个客户端连接请求的所有信息 vio_tmp=vio_new(new_sock, VIO_TYPE_SOCKET, VIO_LOCALHOST); //  网络操作抽象层 my_net_init(&thd->net,vio_tmp)); //  初始化任务线程描述符的网络操作 create_new_thread(thd); //  创建任务线程 } }
MySQL 创建连接 (1) 主要代码在 sql/mysqld.cc 中 (create_new_thread/create_thread_to_handle_connection) ,精简后的代码如下: static void create_new_thread(THD *thd) { NET *net=&thd->net; if (connection_count >= max_connections + 1 || abort_loop) { //  看看当前连接数是不是超过了系统配置允许的最大值,如果是就断开连接。 close_connection(thd, ER_CON_COUNT_ERROR, 1); delete thd; } ++connection_count; thread_scheduler.add_connection(thd); //  将新连接加入到 thread_scheduler 的连接队列中。 }
MySQL 创建连接 (2) 而 thread_scheduler 转而调用 create_thread_to_handle_connection, 精简后的代码如下: void create_thread_to_handle_connection(THD *thd) { if (cached_thread_count > wake_thread) { // 看当前工作线程缓存 (thread_cache) 中有否空余的线程 thread_cache.append(thd); pthread_cond_signal(&COND_thread_cache); //  有的话则唤醒一个线程来用 } else { threads.append(thd); pthread_create(&thd->real_id,&connection_attrib,  handle_one_connection,  (void*) thd))); // 没有可用空闲线程则创建一个新的线程 } }
MySQL 创建连接 (3) 创建连接使用 handle_one_connection 函数 , 精简代码如下 : pthread_handler_t handle_one_connection(void *arg) { thread_scheduler.init_new_connection_thread(); //  初始化线程预处理操作 setup_connection_thread_globals(thd); // 载入一些 Session 级变量 for (;;) {  lex_start(thd); // 初始化 LEX 词法解析器 login_connection(thd); //  进行连接身份验证 prepare_new_connection_state(thd); //  初始化线程 Status, 即 show status 看到的 do_command(thd); //  处理命令 end_connection(thd); // 没事做了关闭连接 , 丢入线程池 } }
MySQL 执行 Query(1) do_command 函数在 sql/sql_parse.cc 定义 , 代码如下 : bool do_command(THD *thd) { NET *net= &thd->net; packet_length = my_net_read(net); packet = (char*) net->read_pos; command = (enum enum_server_command) (uchar) packet[0]; //  解析客户端传过来的命令类型 dispatch_command(command, thd, packet+1, (uint) (packet_length-1)); }
MySQL 执行 Query(2) 再看 dispatch_command 函数在 sql/sql_parse.cc 定义 , 精简代码如下 : bool dispatch_command(enum enum_server_command command, THD *thd, char* packet, uint packet_length) { NET *net = &thd->net; thd->command = command;  switch (command) { // 判断命令类型 case COM_INIT_DB: ...; case COM_TABLE_DUMP: ...; case COM_CHANGE_USER: ...; ... case COM_QUERY: // 如果是 Query alloc_query(thd, packet, packet_length); // 从网络数据包中读取 Query 并存入 thd->query mysql_parse(thd, thd->query, thd->query_length, &end_of_stmt); // 送去解析 } }
MySQL 执行 Query(3) mysql_parse 函数负责解析 SQL(sql/sql_parse.cc), 精简代码如下 : void mysql_parse(THD *thd, const char *inBuf, uint length, const char ** found_semicolon) { lex_start(thd); // 初始化线程解析描述符 if (query_cache_send_result_to_client(thd, (char*) inBuf, length) <= 0) { //  看 query cache 中有否命中,有就直接返回结果,否则进行查找 Parser_state parser_state(thd, inBuf, length);  parse_sql(thd, & parser_state, NULL); //  解析 SQL 语句 mysql_execute_command(thd); //  执行 } }
MySQL 执行 Query(4) 终于开始执行鸟 ~mysql_execute_command 接近 3k 行 ......, 非常精简代码如下 : int mysql_execute_command(THD *thd) { LEX  *lex= thd->lex;  //  解析过后的 SQL 语句的语法结构 TABLE_LIST *all_tables = lex->query_tables;  //  该语句要访问的表的列表 switch (lex->sql_command) { ... case SQLCOM_INSERT: insert_precheck(thd, all_tables); mysql_insert(thd, all_tables, lex->field_list, lex->many_values, lex->update_list, lex->value_list, lex->duplicates, lex->ignore); break; ...  case SQLCOM_SELECT: check_table_access(thd, lex->exchange ? SELECT_ACL | FILE_ACL :  SELECT_ACL,  all_tables, UINT_MAX, FALSE);  //  检查用户对数据表的访问权限 execute_sqlcom_select(thd, all_tables);  //  执行 select 语句 break; } }
MySQL 执行 Query(5) 我们看一个例子 , mysql_insert ( 在 sql/sql_insert.cc), 精简代码如下 : bool mysql_insert(THD *thd, TABLE_LIST *table_list,  //  该 INSERT 要用到的表 List<Item> &fields,  //  使用的项 ....) { open_and_lock_tables(thd, table_list); //  这里的锁只是防止表结构修改 mysql_prepare_insert(...); foreach value in values_list { write_record(...); } } // 里面还有很多处理 trigger ,错误, view 之类的杂七杂八的东西,我们都忽略。
MySQL 执行 Query(6) 我们接着看真正写数据的函数 write_record ( 在 sql/sql_insert.cc), 精简代码如下 : int write_record(THD *thd, TABLE *table,COPY_INFO *info) {  //  写数据记录 if (info->handle_duplicates == DUP_REPLACE || info->handle_duplicates == DUP_UPDATE) { // 如果是 REPLACE 或 UPDATE 则替换数据 table->file->ha_write_row(table->record[0]); table->file->ha_update_row(table->record[1], table->record[0])); } else { table->file->ha_write_row(table->record[0]); } } int handler::ha_write_row(uchar *buf) { // 这是啥 ? Handler API ! write_row(buf);  //  调用具体的实现 binlog_log_row(table, 0, buf, log_func));  //  写 binlog }
MySQL 执行 Query(7)

More Related Content

What's hot (20)

Maxscale ?? 1.1.1
Maxscale ?? 1.1.1Maxscale ?? 1.1.1
Maxscale ?? 1.1.1
NeoClova
?
MariaDB MaxScale
MariaDB MaxScaleMariaDB MaxScale
MariaDB MaxScale
MariaDB plc
?
Using galera replication to create geo distributed clusters on the wan
Using galera replication to create geo distributed clusters on the wanUsing galera replication to create geo distributed clusters on the wan
Using galera replication to create geo distributed clusters on the wan
Codership Oy - Creators of Galera Cluster
?
MongoDB Security Introduction - Presentation
MongoDB Security Introduction - PresentationMongoDB Security Introduction - Presentation
MongoDB Security Introduction - Presentation
HabileLabs
?
Introduction to Elasticsearch
Introduction to ElasticsearchIntroduction to Elasticsearch
Introduction to Elasticsearch
Ismaeel Enjreny
?
RADIUS and LDAP on pfSense 2.4 - pfSense Hangout February 2018
RADIUS and LDAP on pfSense 2.4 - pfSense Hangout February 2018RADIUS and LDAP on pfSense 2.4 - pfSense Hangout February 2018
RADIUS and LDAP on pfSense 2.4 - pfSense Hangout February 2018
Netgate
?
MySQL Shell - The Best MySQL DBA Tool
MySQL Shell - The Best MySQL DBA ToolMySQL Shell - The Best MySQL DBA Tool
MySQL Shell - The Best MySQL DBA Tool
Miguel Araújo
?
[???????] ????? ????? v1.3
[???????] ????? ????? v1.3[???????] ????? ????? v1.3
[???????] ????? ????? v1.3
Ji-Woong Choi
?
Tso and ispf
Tso and ispfTso and ispf
Tso and ispf
satish090909
?
Chicago Data Summit: Apache HBase: An Introduction
Chicago Data Summit: Apache HBase: An IntroductionChicago Data Summit: Apache HBase: An Introduction
Chicago Data Summit: Apache HBase: An Introduction
Cloudera, Inc.
?
Nfs
NfsNfs
Nfs
tmavroidis
?
Apache doris (incubating) introduction
Apache doris (incubating) introductionApache doris (incubating) introduction
Apache doris (incubating) introduction
leanderlee2
?
?3????? ???? ?????? - Pacemaker
?3????? ???? ?????? - Pacemaker?3????? ???? ?????? - Pacemaker
?3????? ???? ?????? - Pacemaker
Tommy Lee
?
Redis database
Redis databaseRedis database
Redis database
?áwrás ?zár
?
HBaseCon 2013: Apache HBase Table Snapshots
HBaseCon 2013: Apache HBase Table SnapshotsHBaseCon 2013: Apache HBase Table Snapshots
HBaseCon 2013: Apache HBase Table Snapshots
Cloudera, Inc.
?
IBM Spectrum Scale Authentication For Object - Deep Dive
IBM Spectrum Scale Authentication For Object - Deep Dive IBM Spectrum Scale Authentication For Object - Deep Dive
IBM Spectrum Scale Authentication For Object - Deep Dive
Smita Raut
?
MySQL GTID ????
MySQL GTID ????MySQL GTID ????
MySQL GTID ????
I Goo Lee
?
100 M pps on PC.
100 M pps on PC.100 M pps on PC.
100 M pps on PC.
Redge Technologies
?
MariaDB Galera Cluster - Simple, Transparent, Highly Available
MariaDB Galera Cluster - Simple, Transparent, Highly AvailableMariaDB Galera Cluster - Simple, Transparent, Highly Available
MariaDB Galera Cluster - Simple, Transparent, Highly Available
MariaDB Corporation
?
Introduction to failover clustering with sql server
Introduction to failover clustering with sql serverIntroduction to failover clustering with sql server
Introduction to failover clustering with sql server
Eduardo Castro
?
Maxscale ?? 1.1.1
Maxscale ?? 1.1.1Maxscale ?? 1.1.1
Maxscale ?? 1.1.1
NeoClova
?
MongoDB Security Introduction - Presentation
MongoDB Security Introduction - PresentationMongoDB Security Introduction - Presentation
MongoDB Security Introduction - Presentation
HabileLabs
?
Introduction to Elasticsearch
Introduction to ElasticsearchIntroduction to Elasticsearch
Introduction to Elasticsearch
Ismaeel Enjreny
?
RADIUS and LDAP on pfSense 2.4 - pfSense Hangout February 2018
RADIUS and LDAP on pfSense 2.4 - pfSense Hangout February 2018RADIUS and LDAP on pfSense 2.4 - pfSense Hangout February 2018
RADIUS and LDAP on pfSense 2.4 - pfSense Hangout February 2018
Netgate
?
MySQL Shell - The Best MySQL DBA Tool
MySQL Shell - The Best MySQL DBA ToolMySQL Shell - The Best MySQL DBA Tool
MySQL Shell - The Best MySQL DBA Tool
Miguel Araújo
?
[???????] ????? ????? v1.3
[???????] ????? ????? v1.3[???????] ????? ????? v1.3
[???????] ????? ????? v1.3
Ji-Woong Choi
?
Chicago Data Summit: Apache HBase: An Introduction
Chicago Data Summit: Apache HBase: An IntroductionChicago Data Summit: Apache HBase: An Introduction
Chicago Data Summit: Apache HBase: An Introduction
Cloudera, Inc.
?
Apache doris (incubating) introduction
Apache doris (incubating) introductionApache doris (incubating) introduction
Apache doris (incubating) introduction
leanderlee2
?
?3????? ???? ?????? - Pacemaker
?3????? ???? ?????? - Pacemaker?3????? ???? ?????? - Pacemaker
?3????? ???? ?????? - Pacemaker
Tommy Lee
?
HBaseCon 2013: Apache HBase Table Snapshots
HBaseCon 2013: Apache HBase Table SnapshotsHBaseCon 2013: Apache HBase Table Snapshots
HBaseCon 2013: Apache HBase Table Snapshots
Cloudera, Inc.
?
IBM Spectrum Scale Authentication For Object - Deep Dive
IBM Spectrum Scale Authentication For Object - Deep Dive IBM Spectrum Scale Authentication For Object - Deep Dive
IBM Spectrum Scale Authentication For Object - Deep Dive
Smita Raut
?
MySQL GTID ????
MySQL GTID ????MySQL GTID ????
MySQL GTID ????
I Goo Lee
?
MariaDB Galera Cluster - Simple, Transparent, Highly Available
MariaDB Galera Cluster - Simple, Transparent, Highly AvailableMariaDB Galera Cluster - Simple, Transparent, Highly Available
MariaDB Galera Cluster - Simple, Transparent, Highly Available
MariaDB Corporation
?
Introduction to failover clustering with sql server
Introduction to failover clustering with sql serverIntroduction to failover clustering with sql server
Introduction to failover clustering with sql server
Eduardo Castro
?

Similar to 惭测厂蚕尝源码分析.01.代码结构与基本流程 (20)

Altibase管理培训 安装篇
Altibase管理培训 安装篇Altibase管理培训 安装篇
Altibase管理培训 安装篇
小新 制造
?
MongoDB for C# developer
MongoDB for C# developerMongoDB for C# developer
MongoDB for C# developer
dianming.song
?
康盛创想项目部Linux 服务器部署标准(最新版)
康盛创想项目部Linux 服务器部署标准(最新版)康盛创想项目部Linux 服务器部署标准(最新版)
康盛创想项目部Linux 服务器部署标准(最新版)
Yiwei Ma
?
X64服务器 lamp服务器部署标准 new
X64服务器 lamp服务器部署标准 newX64服务器 lamp服务器部署标准 new
X64服务器 lamp服务器部署标准 new
Yiwei Ma
?
Row Set初步学习V1.1
Row Set初步学习V1.1Row Set初步学习V1.1
Row Set初步学习V1.1
Zianed Hou
?
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
tidesq
?
惭测厂蚕尝新技术探索与实践
惭测厂蚕尝新技术探索与实践惭测厂蚕尝新技术探索与实践
惭测厂蚕尝新技术探索与实践
Lixun Peng
?
Lucene 全文检索实践
Lucene 全文检索实践Lucene 全文检索实践
Lucene 全文检索实践
yiditushe
?
惭测蝉辩濒展示功能与源码对应
惭测蝉辩濒展示功能与源码对应惭测蝉辩濒展示功能与源码对应
惭测蝉辩濒展示功能与源码对应
zhaolinjnu
?
Mysql 101014202926-phpapp01
Mysql 101014202926-phpapp01Mysql 101014202926-phpapp01
Mysql 101014202926-phpapp01
Bob Huang
?
贬补诲辞辞辫基础及丑颈惫别入门
贬补诲辞辞辫基础及丑颈惫别入门贬补诲辞辞辫基础及丑颈惫别入门
贬补诲辞辞辫基础及丑颈惫别入门
haiwang
?
尘测蝉辩濒总结
尘测蝉辩濒总结尘测蝉辩濒总结
尘测蝉辩濒总结
haiwang
?
Mysql handlersocket
Mysql handlersocketMysql handlersocket
Mysql handlersocket
pwesh
?
Oracle Data Buffer Cache
Oracle Data Buffer CacheOracle Data Buffer Cache
Oracle Data Buffer Cache
Sky Jian
?
颁补蝉蝉补苍诲谤补的初步使用及一些简单的操作
颁补蝉蝉补苍诲谤补的初步使用及一些简单的操作颁补蝉蝉补苍诲谤补的初步使用及一些简单的操作
颁补蝉蝉补苍诲谤补的初步使用及一些简单的操作
zhubin885
?
Mongo db技术交流
Mongo db技术交流Mongo db技术交流
Mongo db技术交流
liuts
?
PHP Coding Standard and 50+ Programming Skills
PHP Coding Standard and 50+ Programming SkillsPHP Coding Standard and 50+ Programming Skills
PHP Coding Standard and 50+ Programming Skills
Ho Kim
?
Altibase管理培训 安装篇
Altibase管理培训 安装篇Altibase管理培训 安装篇
Altibase管理培训 安装篇
小新 制造
?
MongoDB for C# developer
MongoDB for C# developerMongoDB for C# developer
MongoDB for C# developer
dianming.song
?
康盛创想项目部Linux 服务器部署标准(最新版)
康盛创想项目部Linux 服务器部署标准(最新版)康盛创想项目部Linux 服务器部署标准(最新版)
康盛创想项目部Linux 服务器部署标准(最新版)
Yiwei Ma
?
X64服务器 lamp服务器部署标准 new
X64服务器 lamp服务器部署标准 newX64服务器 lamp服务器部署标准 new
X64服务器 lamp服务器部署标准 new
Yiwei Ma
?
Row Set初步学习V1.1
Row Set初步学习V1.1Row Set初步学习V1.1
Row Set初步学习V1.1
Zianed Hou
?
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
Linux c++ 编程之链接与装载 -提高篇--v0.3--20120509
tidesq
?
惭测厂蚕尝新技术探索与实践
惭测厂蚕尝新技术探索与实践惭测厂蚕尝新技术探索与实践
惭测厂蚕尝新技术探索与实践
Lixun Peng
?
Lucene 全文检索实践
Lucene 全文检索实践Lucene 全文检索实践
Lucene 全文检索实践
yiditushe
?
惭测蝉辩濒展示功能与源码对应
惭测蝉辩濒展示功能与源码对应惭测蝉辩濒展示功能与源码对应
惭测蝉辩濒展示功能与源码对应
zhaolinjnu
?
Mysql 101014202926-phpapp01
Mysql 101014202926-phpapp01Mysql 101014202926-phpapp01
Mysql 101014202926-phpapp01
Bob Huang
?
贬补诲辞辞辫基础及丑颈惫别入门
贬补诲辞辞辫基础及丑颈惫别入门贬补诲辞辞辫基础及丑颈惫别入门
贬补诲辞辞辫基础及丑颈惫别入门
haiwang
?
尘测蝉辩濒总结
尘测蝉辩濒总结尘测蝉辩濒总结
尘测蝉辩濒总结
haiwang
?
Mysql handlersocket
Mysql handlersocketMysql handlersocket
Mysql handlersocket
pwesh
?
Oracle Data Buffer Cache
Oracle Data Buffer CacheOracle Data Buffer Cache
Oracle Data Buffer Cache
Sky Jian
?
颁补蝉蝉补苍诲谤补的初步使用及一些简单的操作
颁补蝉蝉补苍诲谤补的初步使用及一些简单的操作颁补蝉蝉补苍诲谤补的初步使用及一些简单的操作
颁补蝉蝉补苍诲谤补的初步使用及一些简单的操作
zhubin885
?
Mongo db技术交流
Mongo db技术交流Mongo db技术交流
Mongo db技术交流
liuts
?
PHP Coding Standard and 50+ Programming Skills
PHP Coding Standard and 50+ Programming SkillsPHP Coding Standard and 50+ Programming Skills
PHP Coding Standard and 50+ Programming Skills
Ho Kim
?

More from Lixun Peng (20)

Double Sync Replication
Double Sync ReplicationDouble Sync Replication
Double Sync Replication
Lixun Peng
?
惭测厂蚕尝新技术探索与实践
惭测厂蚕尝新技术探索与实践惭测厂蚕尝新技术探索与实践
惭测厂蚕尝新技术探索与实践
Lixun Peng
?
阿里云RDS for MySQL的若干优化
阿里云RDS for MySQL的若干优化阿里云RDS for MySQL的若干优化
阿里云RDS for MySQL的若干优化
Lixun Peng
?
顿辞耻产濒别叠颈苍濒辞驳方案
顿辞耻产濒别叠颈苍濒辞驳方案顿辞耻产濒别叠颈苍濒辞驳方案
顿辞耻产濒别叠颈苍濒辞驳方案
Lixun Peng
?
Alibaba patches in MariaDB
Alibaba patches in MariaDBAlibaba patches in MariaDB
Alibaba patches in MariaDB
Lixun Peng
?
Time Machine
Time MachineTime Machine
Time Machine
Lixun Peng
?
MySQL优化、新特性和新架构 彭立勋
MySQL优化、新特性和新架构 彭立勋MySQL优化、新特性和新架构 彭立勋
MySQL优化、新特性和新架构 彭立勋
Lixun Peng
?
对惭测厂蚕尝应用的一些总结
对惭测厂蚕尝应用的一些总结对惭测厂蚕尝应用的一些总结
对惭测厂蚕尝应用的一些总结
Lixun Peng
?
对惭测厂蚕尝的一些改进想法和实现
对惭测厂蚕尝的一些改进想法和实现对惭测厂蚕尝的一些改进想法和实现
对惭测厂蚕尝的一些改进想法和实现
Lixun Peng
?
MySQL多机房容灾设计(with Multi-Master)
MySQL多机房容灾设计(with Multi-Master)MySQL多机房容灾设计(with Multi-Master)
MySQL多机房容灾设计(with Multi-Master)
Lixun Peng
?
Performance of fractal tree databases
Performance of fractal tree databasesPerformance of fractal tree databases
Performance of fractal tree databases
Lixun Peng
?
MySQL源码分析.03.InnoDB 物理文件格式与数据恢复
MySQL源码分析.03.InnoDB 物理文件格式与数据恢复MySQL源码分析.03.InnoDB 物理文件格式与数据恢复
MySQL源码分析.03.InnoDB 物理文件格式与数据恢复
Lixun Peng
?
MySQL源码分析.02.Handler API
MySQL源码分析.02.Handler APIMySQL源码分析.02.Handler API
MySQL源码分析.02.Handler API
Lixun Peng
?
内部惭测厂蚕尝培训.3.基本原理
内部惭测厂蚕尝培训.3.基本原理内部惭测厂蚕尝培训.3.基本原理
内部惭测厂蚕尝培训.3.基本原理
Lixun Peng
?
内部惭测厂蚕尝培训.2.高级应用
内部惭测厂蚕尝培训.2.高级应用内部惭测厂蚕尝培训.2.高级应用
内部惭测厂蚕尝培训.2.高级应用
Lixun Peng
?
内部惭测厂蚕尝培训.1.基础技能
内部惭测厂蚕尝培训.1.基础技能内部惭测厂蚕尝培训.1.基础技能
内部惭测厂蚕尝培训.1.基础技能
Lixun Peng
?
对简易几何机械化证明的进一步研究
对简易几何机械化证明的进一步研究对简易几何机械化证明的进一步研究
对简易几何机械化证明的进一步研究
Lixun Peng
?
A binary graphics recognition algorithm based on fitting function
A binary graphics recognition algorithm based on fitting functionA binary graphics recognition algorithm based on fitting function
A binary graphics recognition algorithm based on fitting function
Lixun Peng
?
一种基于拟合函数的图形识别算法
一种基于拟合函数的图形识别算法一种基于拟合函数的图形识别算法
一种基于拟合函数的图形识别算法
Lixun Peng
?
中文分词算法设计
中文分词算法设计中文分词算法设计
中文分词算法设计
Lixun Peng
?
Double Sync Replication
Double Sync ReplicationDouble Sync Replication
Double Sync Replication
Lixun Peng
?
惭测厂蚕尝新技术探索与实践
惭测厂蚕尝新技术探索与实践惭测厂蚕尝新技术探索与实践
惭测厂蚕尝新技术探索与实践
Lixun Peng
?
阿里云RDS for MySQL的若干优化
阿里云RDS for MySQL的若干优化阿里云RDS for MySQL的若干优化
阿里云RDS for MySQL的若干优化
Lixun Peng
?
顿辞耻产濒别叠颈苍濒辞驳方案
顿辞耻产濒别叠颈苍濒辞驳方案顿辞耻产濒别叠颈苍濒辞驳方案
顿辞耻产濒别叠颈苍濒辞驳方案
Lixun Peng
?
Alibaba patches in MariaDB
Alibaba patches in MariaDBAlibaba patches in MariaDB
Alibaba patches in MariaDB
Lixun Peng
?
MySQL优化、新特性和新架构 彭立勋
MySQL优化、新特性和新架构 彭立勋MySQL优化、新特性和新架构 彭立勋
MySQL优化、新特性和新架构 彭立勋
Lixun Peng
?
对惭测厂蚕尝应用的一些总结
对惭测厂蚕尝应用的一些总结对惭测厂蚕尝应用的一些总结
对惭测厂蚕尝应用的一些总结
Lixun Peng
?
对惭测厂蚕尝的一些改进想法和实现
对惭测厂蚕尝的一些改进想法和实现对惭测厂蚕尝的一些改进想法和实现
对惭测厂蚕尝的一些改进想法和实现
Lixun Peng
?
MySQL多机房容灾设计(with Multi-Master)
MySQL多机房容灾设计(with Multi-Master)MySQL多机房容灾设计(with Multi-Master)
MySQL多机房容灾设计(with Multi-Master)
Lixun Peng
?
Performance of fractal tree databases
Performance of fractal tree databasesPerformance of fractal tree databases
Performance of fractal tree databases
Lixun Peng
?
MySQL源码分析.03.InnoDB 物理文件格式与数据恢复
MySQL源码分析.03.InnoDB 物理文件格式与数据恢复MySQL源码分析.03.InnoDB 物理文件格式与数据恢复
MySQL源码分析.03.InnoDB 物理文件格式与数据恢复
Lixun Peng
?
MySQL源码分析.02.Handler API
MySQL源码分析.02.Handler APIMySQL源码分析.02.Handler API
MySQL源码分析.02.Handler API
Lixun Peng
?
内部惭测厂蚕尝培训.3.基本原理
内部惭测厂蚕尝培训.3.基本原理内部惭测厂蚕尝培训.3.基本原理
内部惭测厂蚕尝培训.3.基本原理
Lixun Peng
?
内部惭测厂蚕尝培训.2.高级应用
内部惭测厂蚕尝培训.2.高级应用内部惭测厂蚕尝培训.2.高级应用
内部惭测厂蚕尝培训.2.高级应用
Lixun Peng
?
内部惭测厂蚕尝培训.1.基础技能
内部惭测厂蚕尝培训.1.基础技能内部惭测厂蚕尝培训.1.基础技能
内部惭测厂蚕尝培训.1.基础技能
Lixun Peng
?
对简易几何机械化证明的进一步研究
对简易几何机械化证明的进一步研究对简易几何机械化证明的进一步研究
对简易几何机械化证明的进一步研究
Lixun Peng
?
A binary graphics recognition algorithm based on fitting function
A binary graphics recognition algorithm based on fitting functionA binary graphics recognition algorithm based on fitting function
A binary graphics recognition algorithm based on fitting function
Lixun Peng
?
一种基于拟合函数的图形识别算法
一种基于拟合函数的图形识别算法一种基于拟合函数的图形识别算法
一种基于拟合函数的图形识别算法
Lixun Peng
?
中文分词算法设计
中文分词算法设计中文分词算法设计
中文分词算法设计
Lixun Peng
?

惭测厂蚕尝源码分析.01.代码结构与基本流程

  • 2. Topics MySQL 基本架构 源码目录结构 核心类库与函数 主要模块 数据流
  • 4. MySQL 目录结构 (1) BUILD : 内含在各个平台、各种编译器下进行编译的脚本。如 compile-pentium-debug 表示在 pentium 架构上进行调试编译的脚本。 client : 客户端工具,如 mysql,mysqladmin 之类。 cmd-line-utils : readline,libedit 工具。 config : 给 aclocal 使用的配置文件。 dbug : 提供一些调试用的宏定义。 Docs : MySQL 在不同平台下的参考手册 extra : 提供 innochecksum,resolveip 等额外的小工具。 include : 包含的头文件 libmysql : 库文件,生产 libmysqlclient.so 。 libmysql_r : 线程安全的库文件,生成 libmysqlclient_r.so 。 libmysqld : 嵌入式 MySQL Server 库 . libservices : 5.5.0 中新加的目录,实现了打印功能。
  • 5. MySQL 目录结构 (2) man : 适合 man 命令查看的帮助文件。 mysql-test : mysqld 的测试工具套件。 mysys : 为实现跨平台, MySQL 自己实现了一套常用的数据结构和算法,如 string, hash 等。还包含一些底层函数的跨平台封装 , 一般以 my_ 开头。 netware : 在 netware 平台上进行编译时需要的工具和库。 plugin : MySQL 5.1 开始支持一个插件式 API 接口 , 不需要重启 mysqld 即可动态载入插件 ,FullText 就是一个例子。 pstack : GNU 异步栈追踪工具。 regex : 正则表达式实现 ( 来自多伦多大学 Henry Spencer 大牛的源码 ) 。 scripts : 提供脚本工具,如 mysql_install_db/mysqld_safe 等。 server-tools: 包含 instance_manager 子目录 , 负责实例的本地和远程管理。
  • 6. MySQL 目录结构 (3) sql: MySQL Server 主要代码,将会生成 mysqld 文件。 sql-bench: 一些基准测试代码代码 , 主要是 Perl 程序 ( 虽然后缀是 sh) 。 sql-common: 存放部分服务器端和客户端都会用到的代码 , 有些地方的同名文件是这里 lin 过去的。 storage : 存储引擎所在目录。 strings : string 库 , 包含很多字符串处理的函数。 support-files : my.cnf 示例配置文件及编译所需的一些工具。 tests : 测试文件所在目录。 unittest : 单元测试文件。 vio : 虚拟 io 系统,是对 network io 的封装 , 把不同的协议封装成统一的 IO 函数。 win : 在 windows 平台编译所需的文件和一些说明。 zlib : zlib 算法库 (GNU)
  • 7. InnoDB 目录结构 (1) btr: B+ 树的实现 buf : 缓冲池的实现 , 包括 LRU 算法 ,Flush 刷新算法等 dict : InnoDB 内存数据字典的实现 dyn : InnoDB 动态数组的实现 fil : InnoDB 文件数据结构以及对于文件的一些操作 fsp : 对 InnoDB 物理文件的管理 , 如页 / 区 / 段等 ( 即 File Space) ha : 哈希算法的实现 handler : 继承与 MySQL 的 handler, 实现 handler API 与 Server 交互 ibuf : 插入缓冲 (Insert Buffer) 的实现 include : InnoDB 所有头文件都放在这个目录 , 是查找结构定义的最佳地点 lock : InnoDB 的锁实现及三种锁算法实现 log: 日志缓冲 (Log Buffer) 和重做日志组 (Redo Log) 的实现
  • 8. InnoDB 目录结构 (2) mem: 辅助缓冲池 (Additional Memory Pool) 的实现 , 用来申请一些内部数据结构的内存 mtr : 事务的底层实现 ( 日志 , 缓冲 ) os : 封装一些对于操作系统的操作 page : 页的实现 , 研究 InnoDB 文件结构 , 这个目录至关重要 pars : 重载部分 MySQL 的 SQL Parser( 有待商榷 ) que : Query graph, 基本上没啥用 read : 读取游标的实现 rem : 行管理操作 ( 比较操作 , 打印等 ) row : 对于各种类型行数据操作的实现 srv : InnoDB 后台线程 , 启动服务 ,Master Thread,SQL 队列等 sync : InnoDB 互斥变量 (Mutex) 的实现 , 基本同步机制 thr : InnoDB 封装的可移植线程库
  • 9. InnoDB 目录结构 (3) trx : 事务的实现 usr : Session 管理 ut : 各种通用小工具
  • 10. 核心类库 THD : 线程类 Item : Item 类 ( 查询条目 , 函数 ,WHERE,ORDER,GROUP,ON 子句等 ) TABLE : 表描述符 TABEL_LIST : JOIN 操作描述符 Field : 列数据类型及属性定义 LEX : 语法树 Protocol : 通讯协议 NET : 网络描述符 handler : 存储引擎接口
  • 11. 核心函数库 (1) 内存操作 : init_alloc_root : 内存池初始化 , 生成内存池根 (MEM_ROOT) alloc_root : 申请内存池内存 , 从 mem_root 制定的内存池申请内存块 free_root : 释放内存池 , 通过 MyFlags 指定哪种内存可以被释放 文件操作 : my_open : 打开一个文件 my_close : 关闭一个文件 my_b_flush_io_cache : 讲数据从内存缓冲写到物理磁盘 end_io_cache : 释放一个 IO_CACHE 对象 哈希操作 : _ hash_init : 初始化 HASH 描述符 hash_search : 搜索哈希表 , 调用 hash_first hash_first : 返回哈希表中找到的第一个行指针 , 否则返回 0
  • 12. 核心函数库 (2) 字符串操作 : strappend : 填充字符串 strmov : 移动字符串到新地址
  • 13. 核心算法 Bitmaps bitmap_init/bimap_free: 创建与释放一个位图 (8*n 个位为单位 ) bitmap_set_bit/bitmap_fast_test_and_set: 设置位图的一个位 bitmap_clear_all/bitmap_set_all: 清空或全部设置一个位图 bitmap_cmp: 对两个位图的特定位比较 Join Buffer 如果存在条件过滤 , 则第一次过滤完的记录将放入 Join Buffer, 避免第二次再判断 Sort Buffer 算法一 : 将排序字段和主键放入 Sort Buffer 排序 , 按照结果用主键取出数据返回 算法二 : 将整行数据放入 Sort Buffer, 排序完成后直接从 Sort Buffer 返回数据
  • 15. MySQL 启动流程 主要代码在 sql/mysqld.cc 中,精简后的代码如下: int main(int argc, char **argv) // 标准入口函数 MY_INIT(argv[0]);// 调用 mysys/My_init.c->my_init() ,初始化 mysql 内部的系统库 logger.init_base(); // 初始化日志功能 init_common_variables(MYSQL_CONFIG_NAME,argc, argv, load_default_groups) // 调用 load_defaults(conf_file_name, groups, &argc, &argv) ,读取配置信息 user_info = check_user(mysqld_user);// 检测启动时的用户选项 set_user(mysqld_user, user_info);// 设置以该用户运行 init_server_components();// 初始化内部的一些组件,如 table_cache, query_cache 等。 network_init();// 初始化网络模块,创建 socket 监听 start_signal_handler();// 创建 pid 文件 mysql_rm_tmp_tables() || acl_init(opt_noacl)// 删除 tmp_table 并初始化数据库级别的权限。 init_status_vars(); // 初始化 mysql 中的 status 变量 start_handle_manager();// 创建 manager 线程 handle_connections_sockets();// 主要处理函数,处理新的连接并创建新的线程处理
  • 16. MySQL 监听连接 主要代码在 sql/mysqld.cc 中 (handle_connections_sockets) ,精简后的代码如下: pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) { FD_SET(unix_sock,&clientFDs); // unix_socket 在 network_init 中被打开 while (!abort_loop) { // abort_loop 是全局变量,在某些情况下被置为 1 表示要退出。 readFDs=clientFDs; // 需要监听的 socket select((int) max_used_connection,&readFDs,0,0,0); // select 异步 (? 科学家解释下是同步还是异步 ) 监听,当接收到 ?? 以后返回。 new_sock = accept(sock, my_reinterpret_cast(struct sockaddr *) (&cAddr), &length); // 接受请求 thd= new THD; // 创建 mysqld 任务线程描述符,它封装了一个客户端连接请求的所有信息 vio_tmp=vio_new(new_sock, VIO_TYPE_SOCKET, VIO_LOCALHOST); // 网络操作抽象层 my_net_init(&thd->net,vio_tmp)); // 初始化任务线程描述符的网络操作 create_new_thread(thd); // 创建任务线程 } }
  • 17. MySQL 创建连接 (1) 主要代码在 sql/mysqld.cc 中 (create_new_thread/create_thread_to_handle_connection) ,精简后的代码如下: static void create_new_thread(THD *thd) { NET *net=&thd->net; if (connection_count >= max_connections + 1 || abort_loop) { // 看看当前连接数是不是超过了系统配置允许的最大值,如果是就断开连接。 close_connection(thd, ER_CON_COUNT_ERROR, 1); delete thd; } ++connection_count; thread_scheduler.add_connection(thd); // 将新连接加入到 thread_scheduler 的连接队列中。 }
  • 18. MySQL 创建连接 (2) 而 thread_scheduler 转而调用 create_thread_to_handle_connection, 精简后的代码如下: void create_thread_to_handle_connection(THD *thd) { if (cached_thread_count > wake_thread) { // 看当前工作线程缓存 (thread_cache) 中有否空余的线程 thread_cache.append(thd); pthread_cond_signal(&COND_thread_cache); // 有的话则唤醒一个线程来用 } else { threads.append(thd); pthread_create(&thd->real_id,&connection_attrib, handle_one_connection, (void*) thd))); // 没有可用空闲线程则创建一个新的线程 } }
  • 19. MySQL 创建连接 (3) 创建连接使用 handle_one_connection 函数 , 精简代码如下 : pthread_handler_t handle_one_connection(void *arg) { thread_scheduler.init_new_connection_thread(); // 初始化线程预处理操作 setup_connection_thread_globals(thd); // 载入一些 Session 级变量 for (;;) { lex_start(thd); // 初始化 LEX 词法解析器 login_connection(thd); // 进行连接身份验证 prepare_new_connection_state(thd); // 初始化线程 Status, 即 show status 看到的 do_command(thd); // 处理命令 end_connection(thd); // 没事做了关闭连接 , 丢入线程池 } }
  • 20. MySQL 执行 Query(1) do_command 函数在 sql/sql_parse.cc 定义 , 代码如下 : bool do_command(THD *thd) { NET *net= &thd->net; packet_length = my_net_read(net); packet = (char*) net->read_pos; command = (enum enum_server_command) (uchar) packet[0]; // 解析客户端传过来的命令类型 dispatch_command(command, thd, packet+1, (uint) (packet_length-1)); }
  • 21. MySQL 执行 Query(2) 再看 dispatch_command 函数在 sql/sql_parse.cc 定义 , 精简代码如下 : bool dispatch_command(enum enum_server_command command, THD *thd, char* packet, uint packet_length) { NET *net = &thd->net; thd->command = command; switch (command) { // 判断命令类型 case COM_INIT_DB: ...; case COM_TABLE_DUMP: ...; case COM_CHANGE_USER: ...; ... case COM_QUERY: // 如果是 Query alloc_query(thd, packet, packet_length); // 从网络数据包中读取 Query 并存入 thd->query mysql_parse(thd, thd->query, thd->query_length, &end_of_stmt); // 送去解析 } }
  • 22. MySQL 执行 Query(3) mysql_parse 函数负责解析 SQL(sql/sql_parse.cc), 精简代码如下 : void mysql_parse(THD *thd, const char *inBuf, uint length, const char ** found_semicolon) { lex_start(thd); // 初始化线程解析描述符 if (query_cache_send_result_to_client(thd, (char*) inBuf, length) <= 0) { // 看 query cache 中有否命中,有就直接返回结果,否则进行查找 Parser_state parser_state(thd, inBuf, length); parse_sql(thd, & parser_state, NULL); // 解析 SQL 语句 mysql_execute_command(thd); // 执行 } }
  • 23. MySQL 执行 Query(4) 终于开始执行鸟 ~mysql_execute_command 接近 3k 行 ......, 非常精简代码如下 : int mysql_execute_command(THD *thd) { LEX *lex= thd->lex; // 解析过后的 SQL 语句的语法结构 TABLE_LIST *all_tables = lex->query_tables; // 该语句要访问的表的列表 switch (lex->sql_command) { ... case SQLCOM_INSERT: insert_precheck(thd, all_tables); mysql_insert(thd, all_tables, lex->field_list, lex->many_values, lex->update_list, lex->value_list, lex->duplicates, lex->ignore); break; ... case SQLCOM_SELECT: check_table_access(thd, lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL, all_tables, UINT_MAX, FALSE); // 检查用户对数据表的访问权限 execute_sqlcom_select(thd, all_tables); // 执行 select 语句 break; } }
  • 24. MySQL 执行 Query(5) 我们看一个例子 , mysql_insert ( 在 sql/sql_insert.cc), 精简代码如下 : bool mysql_insert(THD *thd, TABLE_LIST *table_list, // 该 INSERT 要用到的表 List<Item> &fields, // 使用的项 ....) { open_and_lock_tables(thd, table_list); // 这里的锁只是防止表结构修改 mysql_prepare_insert(...); foreach value in values_list { write_record(...); } } // 里面还有很多处理 trigger ,错误, view 之类的杂七杂八的东西,我们都忽略。
  • 25. MySQL 执行 Query(6) 我们接着看真正写数据的函数 write_record ( 在 sql/sql_insert.cc), 精简代码如下 : int write_record(THD *thd, TABLE *table,COPY_INFO *info) { // 写数据记录 if (info->handle_duplicates == DUP_REPLACE || info->handle_duplicates == DUP_UPDATE) { // 如果是 REPLACE 或 UPDATE 则替换数据 table->file->ha_write_row(table->record[0]); table->file->ha_update_row(table->record[1], table->record[0])); } else { table->file->ha_write_row(table->record[0]); } } int handler::ha_write_row(uchar *buf) { // 这是啥 ? Handler API ! write_row(buf); // 调用具体的实现 binlog_log_row(table, 0, buf, log_func)); // 写 binlog }