MySQL源码学习之Connection Manager详解 |
本文标签:MySQL Connection Manager MySQL数据库Connection Manager的相关知识是本文我们主要要介绍到内容,接下来就让我们一起来了解一下吧 。 1.连接的线程数 MySQL支持单线程和多线程两种连接线程数 。如果是单线程,则在同一时刻,只能有一个connection连接到MySQL,其他的连接会被挂起 。如果是多线程,则同一时刻可以支持多个connection同时连接到服务器 。可以通过设置服务器的启动参数来设定连接的线程数:
服务器如何通过参数来选择使用哪种方式的呢?且看服务器中的分支代码:
这段代码出现在get_options函数中,此函数是根据传入的服务器参数,设置相应参数的模式 。由这段代码可以看出,如果定义了EMBEDDED_LIBRARY宏定义(估计应该是嵌入式使用),则调用one_thread_scheduler,即使用单线程 。如果参数小于等于SCHEDULER_ONE_THREAD_PER_CONNECTION,则调用one_thread_per_connection_scheduler,即每个连接一个线程,即多线程 。 至于global_system_variables.thread_handling是如何进行设置的呢?其实就是根据我们传递给服务器的参数--thread-handling进行设置的,参数的设置统一在函数get_options中,其调用mysqld_get_one_option,其中有个分支,代码如下:
对参数初始化有兴趣的可以具体的看下get_options这个函数,这里就不详细讲解了 。 我们来看下one_thread_scheduler和one_thread_per_connection_scheduler的源代码,看下他们都做了些什么?
原来就是设置了一个结构体中scheduler_functions的参数,只不过这些参数是一些函数指针罢了,也就是说在具体的调用中, 只需要调用add_connection或end_thread即可,不需要知道到底是调用了哪个函数,这大概就是一种变形的多态性吧 。 2.初始化网络配置 网络配置比较简单,就是设置端口,创建套接字,绑定端口,监听端口 。实现全部集中在network_init函数中,由于这个函数确 实没什么好讲的,如果对socket不熟悉的话,可以去网上搜索下相关知识 。这里直接给出相应的伪代码:
3.连接的方式 进程间通信的方式不止是SOCKET,还有其他很多方式 。Mysql支持三种连接方式:namepipe、socket和shared memory,即命名管道、套接字和共享内存的方式 。这三种方式是可以共存的 。默认只使用套接字 。 TCP/IP套接字方式是MySQL在任何平台下都提供的连接方式,也是网络中使用得最多的一种方式 。这种方式在TCP/IP连接上建立一个基于网络的连接请求,一般情况下客户端在一台服务器上,而MySQL实例在另一台服务器上,这两台机器通过一个TCP/IP网络连接 。 例如,我可以在Windows服务器下请求一台远程Linux服务器下的MySQL实例 。在Windows 2000、Windows XP、Windows 2003和Windows Vista以及在此之后的 Windows操作系统中,如果两个需要通信的进程在同一台服务器上,那么可以使用命名管道,SQL Server数据库默认安装后的本地连接也使用命名管道 。在MySQL数据库中,需在配置文件中启用--enable-named-pipe选项 。 在MySQL 4.1之后的版本中,MySQL还提供了共享内存的连接方式,在配置文件中添加--shared-memory 。如果想使用共享内存的方式,在连接时,Mysql客户端还必须使用-protocol=memory选项 。启动时可以通过下面的参数进行设置 。
除了在启动时进行参数设置外,也可以通过修改MY.INI文件进行设置 。我们来看下源码中选择连接方式的分支函数handle_connections_methods:
由于对于namepipe和memory share的通信方式不太了解,这里只研究socket的通信方式 。从代码中可以看出,handle_connections_sockets便是socket的设置,我们就来看下它 。 4.socket管理创建新线程 socket管理其实比较简单,直接给出其伪代码:
首先是select函数进行监视socket端口,如果监控到有连接,则通过accept函数接受客户端的连接,然后新建一个THD类,将连接参数全部设置到THD类的参数上,最后调用create_new_thread函数,这个函数便是重点 。 我们进入这个函数,看下做了啥 。
So easy,首先将全局连接数+1,全局线程数+1,然后调用add_connection函数,这个函数就是我们在上面第一步设置连接的 线程数中,one_thread_scheduler和one_thread_per_connection_scheduler中设置的一个参数 。这两者的区别便是是否创建了 一个新的线程来处理到来的连接 。one_thread_scheduler是单线程方式,木有新建线程 。我们重点研究one_thread_per_connection_scheduler,其设置的add_connection函数为create_thread_to_handle_connection:
可见,最后调用了pthread_create函数,这个函数便是创建一个新的线程,新线程的处理函数为handle_one_connection. 5.新线程处理流程 新线程处理函数为handle_one_connection,到此位置,一个新的connection被一个新创建的线程所单独处理 。我们看下其中 是如何进行处理的 。
首先进行了词法分析结构体的初始化,然后进行用户认证,认证成功后通过do_command循环执行客户端发过来的命令 。 6.总结 整个connection manager的流程十分清晰,单线程的连接一般很少使用,大多使用多线程方式 。多线程连接中其实还涉及到线程缓冲池的概念,即如果一个连接断开后,其所创建的线程不会被销毁掉,而是放到缓冲池中,等待下一个新的connection到来时,首先去线程缓冲池查找是否有空闲的线程,有的话直接使用,木有的话才去创建新的线程来管理这个connection 。 关于MySQL数据库Connection Manager的相关知识就介绍到这里了,希望本次的介绍能够对您有所收获! |