MySQL 5.7: 短连接优化

jopen 10年前

尽管比较罕见,但某些场景还是存在着短连接,即用户执行完请求后,很快断开会话。伴随着频繁创建/销毁连接的过程。

官方博客:

http://mysqlserverteam.com/improving-connectdisconnect-performance/

对应worklog: http://dev.mysql.com/worklog/task/?id=6606

在之前的版本中, THD/NET/VIO总是由接受连接请求的线程来完成,如果是长连接这没有问题,但如果都是短连接的话,就会应先main线程接受新连接请求的效率,在WL#6606中,THD和NET的初始化被移动到worker线程来完成。

0. background

增加新目录sql/conn_handler,定义了大量的类来处理连接部分的逻辑。下图简单描述了下各个类的关系,可能不是很全面,只涉及linux平台下面比较常用的类.

MySQL 5.7: 短连接优化

 

增加全局变量:

Connection_acceptor *mysqld_socket_acceptor 用于接受新的连接请求.

Connection_acceptor作为接受socket请求的基类,封装了多种socket请求方式.

Connection_acceptor::m_listener存储了对应的listener对象.

1.主线程监听请求:mysqld_main

初始化 mysqld_socket_acceptor

mysqld.cc:
1692     Mysqld_socket_listener *mysqld_socket_listener=
1693       new (std::nothrow) Mysqld_socket_listener(bind_addr_str,
1694                                                 mysqld_port, back_log,
1695                                                 mysqld_port_timeout,
1696                                                 unix_sock_name);
1697     if (mysqld_socket_listener == NULL)
1698       unireg_abort(1);
1699
1700     mysqld_socket_acceptor=
1701       new (std::nothrow) Connection_acceptor(mysqld_socket_listener);
1702     if (mysqld_socket_acceptor == NULL)
1703     {
1704       delete mysqld_socket_listener;
1705       unireg_abort(1);
1706     }
1707
1708     if (mysqld_socket_acceptor->init_connection_acceptor())
1709     {
1710       delete mysqld_socket_acceptor;
1711       unireg_abort(1);
1712     }

根据thread_handling初始化connection hander:

7381 #ifndef EMBEDDED_LIBRARY
7382   if (Connection_handler_manager::init())
7383   {
7384     sql_print_error(“Could not allocate memory for connection handling”);
7385     return 1;
7386   }
7387 #endif

我们通常用的one thread one connection对应的类为Per_thread_connection_handler

进入监听connection_event_loop —> Mysqld_socket_listener::listen_for_connection_event

当获取到一个新的监听请求时,会创建一个Channel_info类,用来存储用户的socket信息。

 

2. 处理新连接

当从listen_for_connection_event获得新的连接请求后,调用Mgr->process_new_connection处理新请求

在检查是否超出连接数限制后,调用Per_thread_connection_handler::add_connection, 调度thread cache的线程后创建新的线程

 

handle_connection为worker线程入口,传递的参数为对应用户的Channel_info对象,包含了对应的新请求socket,在该函数中进行THD/NET/VIO初始化

sql/conn_handler/connection_handler_per_thread.cc:
259
260   for (;;)
261   {
262     THD *thd= init_new_thd(channel_info);

主要代码:

3.WL#7260对LOCK_thread_count锁进行了拆分

因为在完成上述优化后,性能测试发现瓶颈在LOCK_thread_count锁上,因此在WL#7260中对锁进行了拆分

主要修改摘录自commit log,讲的很清楚,不重复描述了:

LOCK_thread_cache is introduced to protect the thread cache used
by the default connection handler (one thread per connection).Synchronization during startup of signal handler thread is now
done using LOCK_start_signal_handler.

Synchronization during shutdown of main thread connection
listening is now done using LOCK_socket_listener_active.

The global thread_id counter is now incremented using atomics,
rather than being protected by LOCK_thd_count.

THD::current_linfo is now protected by THD::LOCK_thd_data rather
than LOCK_thd_count.

max_used_connections is now reset under protection of
LOCK_connection_count rather than LOCK_thd_count.

worlog连接:

http://dev.mysql.com/worklog/task/?id=7260

代码连接:

http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/6844

 

原创文章,转载请注明: 转载自Simple Life

本文链接地址: MySQL 5.7: 短连接优化