前面讲了mysql的启动,线程的初始化,线程池的基本原理,现在就看看工作线程都在循环中主要干了什么,顺便说一下以后的方向,以后主要会学习mysql的cache原理,大约涉及到6000行左右的代码,不知道什么时候能搞清楚,之后就会进入innodb引擎,主要攻几方面方面:innodb的文件存储结构,索引的实现,锁的实现,事务的实现。
mysql的工作线程调用的函数栈很浅,如果我们在mysql不处理任何命令的情况下挂起整个mysql,那么就可以观察到mysql的工作线程都在等待或者干什么:
写成伪代码就是:
while (thd_is_connection_alive(thd)) { mysql_audit_release(thd); if (do_command(thd)) break; }
就是这个while函数,在sql/source files/sql_connect.cc:867这个文件中,mysql工作线程就是不停的坚持是否需要退出(thd_is_connection_alive),然后尝试read出客户端上发的指令,若没有,那么read阻塞,看来mysql是阻塞read的,一旦read够足够长的指令,那么就会丢给sql_parse.cc的dispatch_command函数根据不同的指令执行对应的代码。这里就有必要看看客户端上发的指令格式是怎么样子的了,先创建个简单的表:
create table customers( id int auto_increment, name varchar(64) not null default '', age int not null default -1, birthday datetime, primary key idx_id(id) )engine=innodb,charset=utf8;
以及插入若干数据,这个表将是未来我们主要的实验表。经过阅读代码和测试发现,mysql的客户端上发格式非常简单,至少我目前还没遇到复杂的格式,格式就是“命令”+“sql语句”。因为mysql和客户端的交流是靠乒乓球方法交流的,也就是我发等你回,我回等你发,总之不是客户端等服务的回就是服务端等客户端发,在这个乒乓球交流中,“球”到了mysql服务端后,mysql先读出前面四个字节,这个四个字节其实就是int,也就是即将收到的sql语句长度,更准确的说是前面提到的“命令”+“sql语句”,mysql就会read出这个长度的信息出来。接着,mysql会把读到的信息保存在thd->net->packet中,thd->net->packet_length则是这个格式的长度。再往后,mysql就会把这些信息传入dispatch_command函数进行解析执行了。
解析完成,会调用end_statement回给客户端,mysql回的内容只有两种,一种是错误码,一种是查询字节流和查询状态,这些以后再细看。
总之mysql和客户端就是这样一个乒乓交流,自己也是不停的做以上这个循环,直到被通知停止为止。