Mysql源代码分析系列(4): 主要调用流程(续)--转载
在上一篇文章中我们讲到了的 mysql_execute_command,这个函数根据解析出来的SQL命令分别调用不同的函数做进一步处理。我们这里先看"INSERT"命令的处 理流程。其对应的处理函数是mysql_insert,在sql/sql_insert.cc中,还是很长,大概300多行。
bool mysql_insert(THD *thd,
TABLE_LIST *table_list, // 该命令要用到的表
List<Item> &fields, // 使用的域
List<List_item> &values_list,
List<Item> &update_fields,
List<Item> &update_values,
enum_duplicates duplic,
bool ignored) {
open_and_lock_tables(thd, table_list);
mysql_prepare_insert(...);
foreach value in values_list {
write_record(...);
}
}
其实里面还有很多处理trigger,错误,view之类的,我们暂时都忽略。
// 写数据记录
int write_record(THD *thd, TABLE *table,COPY_INFO *info) {
if (info->handle_duplicates == DUP_REPLACE || info->handle_duplicates == DUP_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]);
}
}
不用说,这里我们还是省略了好多东西,要注意的是这里调用的table->file->ha_write_row和table->file->ha_update_row。在sql/table.h可以看到table的定义,其中file被定义成handler *file; 那 handler是什么?对了,这就是我们前面提到的数据存储抽象层,所有的存储引擎都必须事先这里定义的接口,才能被mysql使用。在这里使用的具体的 接口操作是ha_write_row和ha_update_row。这两个函数可以在sql/handler.cc中看到。比如 ha_write_row:
int handler::ha_write_row(uchar *buf) {
write_row(buf); // 调用具体的实现
binlog_log_row(table, 0, buf, log_func)); // 写binlog
}
下面我们看看在myisam中是怎么实现的文件操作,代码在storage/myisam/ha_myisam.cc中。先看write_row:
723 int ha_myisam::write_row(uchar *buf)
724 {
725 ha_statistic_increment(&SSV::ha_write_count);
726
727 /* If we have a timestamp column, update it to the current time */
728 if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) // 如果有timestamp域,写入当前时间。
729 table->timestamp_field->set_time();
730
731 /*
732 If we have an auto_increment column and we are writing a changed row
733 or a new row, then update the auto_increment value in the record.
734 */
735 if (table->next_number_field && buf == table->record[0]) // 更新auto_increment列
736 {
737 int error;
738 if ((error= update_auto_increment()))
739 return error;
740 }
741 return mi_write(file,buf); // 真正写文件
742 }
再看mi_write函数,很好找,就在storage/myisam/mi_write.c,我们就不再分析下去了,具体实现和myisam使用的文件格式相关,有兴趣的可以参考myisam的相关文档。
结语
写到这里,我们对于mysql执行sql语句的主要调用流程就有了大概的了解,但是真正的难点往往在细节中,我也刻意逃避了这些细节,但是还是应该列一下相关的内容:
+ Sql语句的解析和相关数据结构
+ Sql语句的描述数据结构
+ 执行优化相关算法
+ 数据存储殷勤抽象层的定义和交互
+ 存储引擎的具体操作和文件格式
必须要提到的是,这些地方的代码都比较难懂,而且核心函数都很长,非常不便与理解,有需要的人可以选一些方面具体深入,但要面面俱到就需要很多时间了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
2007-05-18 EditPlus 使用技巧集萃(转)