Mysql源码学习笔记--偷窥线程

安装完Mysql后,使用VS打开源码开开眼,我嘞个去,这代码和想象中怎么差别这么大呢?感觉代码有些凌乱,注释代码都写的比较随意,好像没有什么统一的规范,不同的文件中代码风格也有差异,可能Mysql经过了很多牛人的手之后,集众牛人之长吧。也可能是我见识比较浅薄,适应了自己的代码风格,井底之蛙了,总之还是怀着敬畏的心情开始咱的源码之旅吧。本人菜鸟,大神轻拍。

  Mysql可以启动起来了,应该怎么学习呢?总不能从main开始一步一步的看吧,Mysql作为比较底层的大型软件,涉及到数据库实现的方方面面,没有厚实的数据库理论基础和对Mysql各个模块相当的熟悉,从main开始势必会把自己引入某个死胡同啊,什么都看,最后啥也不会,咱伤不起。

  经过思考后,我想还是通过客户端来调试服务器,从而学习服务器代码比较现实。也就是通过客户端的动作,看服务器的反应。比如从客户端的登录动作来看SERVER如何进行通信、用户识别、鉴定以及任务分配的,通过CREATE TABLE,来看SERVER如何解析DDL语句以及针对不同的存储引擎采取的不同的物理存储方式,通过INSERT语句,来看SERVER如何进行Btree的操作。通过SELECT语句来看如何进行SQL语句语法树的创建和优化的,通过ROLL BACK,来看SERVER事务是如何实现的。这里主要是通过跟踪代码学习Mysql数据库实现的思想,对于具体的代码不去做过多的追究(主要是我对C++不是很熟悉),好读书,不求甚解,呵呵。

  由此,暂时准备了以下几条SQL语句,来有针对的进行SERVER的分析

1、 LOGIN(登录)

mysql.exe –uroot –p

2、 DDL(建表语句)

create table tb_myisam(c1 int, c2 varchar(256)) engine = myisam;

create table tb_innodb(c1 int, c2 varchar(256)) engine = innodb;

3、 INSERT

Insert into tb_myisam values(1 , ’寂寞的肥肉’);

Insert into tb_innodb values(1 , ’寂寞的肥肉’);

4、 SELECT

Select c1 from tb_myisam;

Select * from tb_innodb;

5、 ROLLBACK

  大家都知道,mysql可以通过多个客户端,进行并发操作,当然也包括登录了。在别人登录的时候,其他的用户可能正在进行一些其它的操作,因此对于登录我们猜测应该有专门的线程负责客户端和服务器的连接的创建,以保证登录的及时性,对于每个连接的用户,应该用一个独立的线程进行任务的执行。

  首先介绍下mysql中创建线程的函数,创建线程的函数貌似就是_begin_thread,CreateThread,我们通过VS在整个解决方案中进行查找,bingo!在my_winthread.c中找到了调用_begin_thread的函数pthread_create,在os0thread.c中找到了调用CreateThread的函数os_thread_create,一个系统怎么封装两个系统函数呢??再仔细看下,发现my_winthread.c是在项目mysys下,而os0thread.c是在项目innobase下。innobase!!这不就是innodb的插件式存储引擎么,原来这是存储引擎自己的封装的底层函数,哥心中豁然开朗了。我想Mysql应用范围如此之广,除了开源之外,插件式的存储引擎功不可没啊,用户可以根据自己的实际应用采取不同的存储引擎,对于大公司,估计会开发自己的存储引擎。

  下面分析下pthread_create是如何调用_begin_thread的,先粗略看下源码。

int pthread_create(pthread_t *thread_id, pthread_attr_t *attr,

pthread_handler func, void *param)

{

HANDLE hThread;

struct pthread_map *map;

DBUG_ENTER("pthread_create");

if (!(map=malloc(sizeof(*map))))

DBUG_RETURN(-1);

map->func=func;

map->param=param;

pthread_mutex_lock(&THR_LOCK_thread);

#ifdef __BORLANDC__

hThread=(HANDLE)_beginthread((void(_USERENTRY *)(void *)) pthread_start,

attr->dwStackSize ? attr->dwStackSize :

65535, (void*) map);

#else

hThread=(HANDLE)_beginthread((void( __cdecl *)(void *)) pthread_start,

attr->dwStackSize ? attr->dwStackSize :

65535, (void*) map);

#endif

DBUG_PRINT("info", ("hThread=%lu",(long) hThread));

*thread_id=map->pthreadself=hThread;

pthread_mutex_unlock(&THR_LOCK_thread);

if (hThread == (HANDLE) -1)

{

int error=errno;

DBUG_PRINT("error",

("Can't create thread to handle request (error %d)",error));

DBUG_RETURN(error ? error : -1);

}

VOID(SetThreadPriority(hThread, attr->priority)) ;

DBUG_RETURN(0);

}

关键的代码是下面三句:

map->func=func;

map->param=param;

_beginthread((void( __cdecl *)(void *)) pthread_start,

attr->dwStackSize ? attr->dwStackSize :

65535, (void*) map);

  从这可以看出,创建的新线程的名字是个固定的函数——pthread_start,而我们传进来的想创建的函数func是挂载在了map上了,函数的参数同样的挂载在map上了,这样我们就可以推理出在pthread_start函数中,肯定会出现这样的代码:

              map->func(map->param);

  mysql没有选择直接_beginthread(func, stack_size, param)的形式,而是进行了一次封装,不知道这样的好处是什么,可能牛人的思想不是我这样小菜鸟能顿悟的,跑题了~~

  至此,我们只在pthread_create函数上设置断点,调试启动mysqld,断点停下来,看下系统的线程状况:

Mysql源码学习笔记--偷窥线程

  我们第一次进入pthread_create,任何线程都没开始创建呢,按理说系统线程应该就只有一个主线程,可现在多了这么多,这些应该是innodb存储引擎创建的线程了(具体是在plugin_init)。根据线程的名称,结合注释,猜测了下这些线程的作用。

   Io_handler_thread:从名称可以知道这些是I/O线程,负责进行磁盘I/O。

Svr_error_monitor_thread:应该是服务器出错监控线程。

Svr_lock_timeout_thread:应该是和上锁相关的线程。

Svr_master_thread:

/*************************************************************************

The master thread controlling the server. */

服务器控制线程,应该是具体进行作业的线程。

Svr_monitor_thread:

/*************************************************************************

A thread prints the info output by various InnoDB monitors. */

监控线程,负责打印信息。

  淡然飘过吧,不去细究了,我们只关心pthread_create创建的线程。根据调试,发现多了几个线程同名的线程_threadstart,如下所示:

Mysql源码学习笔记--偷窥线程

  调试时看堆栈可以知道这三个线程的创建者和作用,如下所示


创建者


处理函数


create_shutdown_thread


handle_shutdown


start_handle_manager


handle_manager


handle_connections_methods


handle_connections_sockets

  创建者:调用pthread_create进行创建线程的函数。

  处理函数:调用pthread_create所创建的线程的具体的线程函数。

  由名称我们就可以看出,handle_connections_sockets应该是处理连接的线程了,从顺序上看,也应该是这样,只有系统中所有的其他必须的线程创建完毕后,才能创建监听线程(连接线程),即监听线程应该是系统最后创建的。

找到了我们LOGIN需要的线程了,下次针对这个线程,分析下如何进行登录的,以及登录后为用户分配哪些资源。时间不早啦,洗洗睡了

摘自 心中无码

分类:默认分类 时间:2012-01-04 人气:7
本文关键词:
分享到:

相关文章

  • Mysql中UNION用法与排序 2012-01-01

      最近也是在写项目中碰到的这个问题,需要将两个SELECT查询结果组合起来进行分组排序,想到了用union方法,用TP的union操作根本无法完成复杂的union操作,于是搜罗了一下,先说一下union的用法,在说一下TP中如何实现复杂的union操作。   一、UNION 用法   一 UNION语法   SELECT ...   UNION[ALL | DISTINCT]   SELECT ...   [UNION [ALL | DISTINCT]   SELECT ...]   UNIO

  • MySQL数据库编码概要 2012-01-01

    大家在使用数据库的时候,总会出现各种各样的编码问题,看了MySQL官方文档后,记录下一些MySQL的编码体系知识,如MySQL有那几层使用编码的地方,MySQL客户端和服务端交互时哪些环节涉及到的编码,和如何指定编码。 基本概念: mysql数据库编码层次:系统层,server层,database层,table层,column层,还有client,connection和result三种和客户端通讯相关的场景;A character set is a set of symbols and enco

  • mysql常用监控脚本命令列表 2012-01-02

    mysql常用监控脚本命令列表 [java] #/bin/sh #检测mysql server是否正常提供服务 mysqladmin -u sky -ppwd -h localhost ping #获取mysql当前的几个状态值 mysqladmin -u sky -ppwd -h localhost status #获取数据库当前的连接信息 mysqladmin -u sky -ppwd -h localhost processlist #mysql dump数据导出 mysqldump -u

  • Linux系统中自带Mysql.Apache.Php卸载 2012-01-04

    卸载步骤如下: 卸载Mysql [[email protected] ~]# rpm -qa|grep mysql mod_auth_mysql-2.6.1-2.2 php-mysql-4.3.9-3.15 mysql-devel-4.1.20-1.RHEL4.1 mysql-4.1.20-1.RHEL4.1 mysqlclient10-3.23.58-4.RHEL4.1 libdbi-dbd-mysql-0.6.5-10.RHEL4.1 说明:rpm –qa | grep mysql 命令是为了把m

  • Mysql version can not be less than 4.1 2012-01-08

      Mysql version can not be less than 4.1   这个直接翻译过来是:Mysql数据库版本不能低于4.1   貌似是数据库版本的问题,真是这样的吗?   经过前后空间数据库版本的观察,前后数据库版本均为5.0,因此不会是数据库版本的问题了。   纠结了一番,竟然:   是没有修改程序和数据库连接的配置文件,汗,这个竟然忘记了,   才导致出现了Mysql version can not be less than 4.1。   于是在网站根目录下找到 confi

  • MySQL在有索引列情况下select *的输出结果顺序 2012-01-08

      创建一个表格,一个是主键列,一个是索引列。然后插入一批数据,调用select * from test_b,可以发现输出结果并没有按照Id有序,而是按照Type有序。   如果希望按照Id有序,可以使用force index (primary)这一hint语句。   mysql> CREATE TABLE `test_b` (   -> `Id` int(11) NOT NULL,   -> `Type` int(11) DEFAULT NULL,   -> PRIMA

  • 免费 500m/php/mysql/ftp/domain空间 2012-01-15

    免费 500m/php教程/mysql教程/ftp/domain空间 免费空间 PHP与MySQL的免费虚拟主机印度尼西亚 磁盘空间:200 MB 每月带宽:500 MB 网站托管:1网站 高级特色:Yess! Free Hosting Free Webhosting indonesia with php & Mysql Disk space: 200 MB Montly Bandwith: 500 MB Website Hosted: 1 Website See Premium Fea

  • 两款国外免费1G php mysql空间 100G/月流量 2012-01-17

    免费1GB空间100GB的带宽无限MySQL,电子邮件,FTP用户,子域名,插件域名,停放的域名。请不要与支付的软件包关联这个包。这个包是供客户端使用,并获得舒适的cPanel,但因为它是可用的,你可以保持这个包aslong。 Browse Products & Services: Free 1GB Space 100GB Bandwidth Unlimited MySQL, Email,FTP Users, Sub Domains, Addon Domains, Parked Doma

  • Windows XP/2008 MySQL 5.1 安装[多图] 2012-01-18

    下面的是MySQL安装的图解,用的可执行文件安装的,详细说明了一下!    打开下载的mysql安装文件mysql-5.0.27-win32.zip,双击解压缩,运行“setup.exe”,出现如下界面: mysql安装向导启动,按“Next”继续 选择安装类型,有“Typical(默认)”、“Complete(完全)”、“Custom(用户自定义)”三个选项,我们选择“Custom”,有更多的选项,也方便熟悉安装过程 在“Developer Components(开发者部分)”上左键单击,选择

Copyright (C) quwantang.com, All Rights Reserved.

趣玩堂 版权所有 京ICP备15002868号

processed in 0.052 (s). 10 q(s)