使用 CodeIgniter 2.x 可以配置 autoload 自动加载数据库,也可以在 Model 的构造函数中使用$this->load->database()
方法加载数据库:
1 | # xxx.model |
database() 方法
$this->load->database()
方法位于 system/core/Loader.php
中,此方法返回 DB($params, $active_record)
1 | /** |
DB() 方法
DB()
方法位于 system/database/DB.php
中,此方法重点完成以下两个任务
new $driver($params)
$DB->initialize()
1 | /** |
当 autoinit 为 true 时,自动初始化数据库,$DB->initialize()
,此方法位于 system/database/DB_driver.php
中
1 | /** |
数据库长连接
根据 $this->pconnect
决定数据库使用长连接或者短连接,$this->pconnect
的取值在数据库配置文件中配置。MySQL 的长连接是存在 php-fpm 子进程里的,进程之间是不共享连接的,所以每个 php-fpm 进程都有一个单独的长连接。使用
ps -aux | grep fpm
和 netstat -anp | grep 3306
可分别查看 fpm 子进程个数和 MySQL 长连接个数相同。
使用 MySQL 长连接可以复用连接通道,减小连接时延,当 PHP 应用访问量不高,并发量不大时,我们只需要开启少量 php-fpm 子进程,每个子进程对应一个 MySQL 连接,但是当应用并发增加, php-fpm 子进程数量扩大时,MySQL 连接数也随之增加,对数据库造成较大压力,特别是当连接数达到数据库上限时会导致其他 fpm 连接异常。因此要注意使用长连接时 fpm 的子进程数不应超过数据库的最大连接数,在数据库中使用SHOW VARIABLES like 'max_connections';
查看数据库最大连接数。
1 | //查看MySQL最大连接数 |
数据库初始化
关于 autoinit
: CI 2.x 中默认为 true, 有些业务场景使用缓存且缓存命中率较高,若启用 autoinit
,处理每个请 PHP 求时都会去连接数据库,耗时严重。使用 strace -c -p 360558
分析 360558 (FPM 进程id) 进程程序执行情况得出, 程序执行时 read 操作耗时最长。
再使用 strace -p 360558 2>&1
查看 360558 (FPM 进程id) 进程程序执行情况发现有大量的 read() 和 write() 操作,经分析发现一个参数为 4 的时候为数据库相关操作。
将 autoinit
改为 false 后,read 和 write 耗时几乎为 0.
需要注意的时将 autoinit 改为 false 后,CI 会报如下错误:
1 | mysql_escape_string(): This function is deprecated; use mysql_real_escape_string() instead. |
参照 https://stackoverflow.com/questions/26169455/codeigniter-use-mysql-real-escape-string-instead-database-connection-issue 修改 system/database/drivers/mysql/mysql_driver.php
下的 escape_str()
为:
1 | function escape_str($str, $like = FALSE) |