说明:测试使用的版本checkout源自https://github.com/jkvor/emysql.git
这个版本在github上已经不再更新了
emysql 也是一个常用的erlang mysql数据库驱动。相比较erlang_mysql_driver,emysql的代码结构更加清晰。emysql的使用非常方便,先执行emysql:start、emysql:add_pool,然后调用emysql:fetch/execute就可以开始执行sql语句了。
网上emysql分析源码的版本众多,发现我下载下来的还跟大部分人下载的不一样,可能该版本修改了很多,我下载了当前最新版本。本来是想分析emysql源码的,测试下发现了几个bug,不知道是不是使用的方式不当。
下面就开始分析下emysql的源码和测试的过程。
(注:使用“业务进程”表示调用emysql:execute的进程)
emysql 启动简要分析
- 1 emysql的启动
emysql:start 以监督树进程的形式,启动了两个子进程,emysql_statements 和 emysql_conn_mgr。
init(_) ->
{ok, {
{one_for_one, 10, 10}, [
{emysql_statements, {emysql_statements, start_link, []}, permanent, 5000, worker, [emysql_statements]},
{emysql_conn_mgr, {emysql_conn_mgr, start_link, []}, permanent, 5000, worker, [emysql_conn_mgr]}
]}}.
2 emysql_statements的启动
emysql_statements在启动时并没有做特殊操作,只是初始化了#state。这里emysql_statements的state里有两个元素statements和prepared,数据结构都是采用gb_trees。3 emysql_conn_mgr的启动
emysql_conn_mgr的state有两个元素pools 和 waiting , 如果app文件一开始配置了连接池则会在启动的时候添加,一般来说是[]。
init([]) ->
Pools = initialize_pools(),
Pools1 = [emysql_conn:open_connections(Pool) || Pool <- Pools],
{ok, #state{pools=Pools1}}.
emysql_conn_mgr这个进程类似于erlang_mysql_driver中的mysql_dispatcher,emysql_conn_mgr管理了多个连接池,连接池里放置了多个连接。另外emysql_conn_mgr还管理了waiting的pid,这些pid是等待连接的业务进程。
测试
- 1 测试一
简要分析后,就开始测试了,同一时间spawn了10万个进程执行select语句,主要目的是想测试下,在这种情况下主要的压力放在哪些进程上了。测试表明,刚开始6秒左右2万多的进程能够得到返回,但是在后面的时间就都是connection_wait_timeont报错了。
execut