/ php

php-mysql

Persistent connections != connection pooling

Connection pooling in PHP

There is no connection pooling in php.

Q: 为什么 PHP 一直在优化程序执行效率,而不优化数据库连接?
A: 至于像java之类那样「真正意义上的连接池」技术,在PHP上是根本不可行的。
PHP就是被设计成每次运行完以后销毁一切状态,任何数据都不会带到下一个执行环境上去的。
所以不可能内置一个全功能的「连接池」,而只能从第三方扩展里实现。
如果你需要全功能连接池技术,那你就不能用PHP而需要用常驻内存型的语言,比如Java,ASPX,Ruby,Python,等等。

MySQL 连接数

MySQL是根据连接数分配资源的,一个连接需要开启一个线程。如果并发1万个请求,那么就需要建立1万个MySQL连接,这会给MySQL-Server带来巨大的压力。线程数量增加后,线程间切换会占用大量CPU资源

查看mariadb数据库最大连接数,默认为151

MariaDB [(none)]> show variables like 'max_connections';  
+-----------------+-------+  
| Variable_name   | Value |  
+-----------------+-------+  
| max_connections |  151  |  
+-----------------+-------+  
➜  ~ vi /etc/my.cnf.d/server.cn
[mysqld]
character-set-server = utf8mb4
max_connections=1000

修改完成后,重新启动 maraidb:

➜  ~ sudo systemctl restart mysql

再次查看mariadb数据库最大连接数,可以看到最大连接数已经是1000

MariaDB [(none)]> show variables like 'max_connections';  
+-----------------+-------+  
| Variable_name   | Value |  
+-----------------+-------+  
| max_connections | 1000  |  
+-----------------+-------+  

如果不是,那就还需要额外修改 mariadb 的默认打开文件数限制,修改 /usr/lib/systemd/system/mariadb.service

[Service]
# 追加以下两行
LimitNOFILE=10000
LimitNPROC=10000

MySQL 长连接

MySQL短连接每次请求操作数据库都需要建立与MySQL服务器建立TCP连接,这是需要时间开销的。TCP连接需要3次网络通信。这样就增加了一定的延时和额外的IO消耗。请求结束后会关闭MySQL连接,还会发生3/4次网络通信。

close操作不会增加响应延时,原因是close后是由操作系统自动进行通信的,应用程序感知不到

长连接就可以避免每次请求都创建连接的开销,节省了时间和IO消耗。提升了PHP程序的性能。

MySQL连接池

连接池是可以有效降低MySQL-Server负载的。原理是 连接池使用一个共享资源的模式,如并发100个请求,实际上并不是每个请求的所有时间都在执行SQL查询。这样100个请求,共享20个MySQL连接就可以满足需求了。当一个请求操作完数据库后,开始进入模板渲染等流程,这时就会释放数据库连接给其他的请求使用。

连接池仅在超大型应用中才有价值。普通的应用采用MySQL长连接方案,每个php-fpm创建一个MySQL连接,每台机器开启100个php-fpm进程。如果有10台机器,每台机器并发的请求为100。实际上只需要创建1000个MySQL连接就能满足需求,数据库的压力并不大。即使有100台机器,硬件配置好的存储服务器依然可以承受。

达到数百或者数千台应用服务器时,MySQL服务器就需要维持十万级的连接。这时数据库的压力就会非常大了。连接池技术就可以派上用场了,可以大大降低数据库连接数。