php pdo mysql 超时_为 PDO 增加读写超时
定义枚举类型
首先,我们先要创建枚举类型,也就是未来在 PHP 代码中,setAttribute 传入的 KEY
原生的这个 key 值都定义在 Zend/ext/pdo/php_pdo_driver.h 中:
enum pdo_attribute_type {
PDO_ATTR_AUTOCOMMIT,/* use to turn on or off auto-commit mode */
PDO_ATTR_PREFETCH,/* configure the prefetch size for drivers that support it. Size is in KB */
PDO_ATTR_TIMEOUT,/* connection timeout in seconds */
PDO_ATTR_ERRMODE,/* control how errors are handled */
PDO_ATTR_SERVER_VERSION,/* database server version */
PDO_ATTR_CLIENT_VERSION,/* client library version */
PDO_ATTR_SERVER_INFO,/* server information */
PDO_ATTR_CONNECTION_STATUS,/* connection status */
PDO_ATTR_CASE,/* control case folding for portability */
PDO_ATTR_CURSOR_NAME,/* name a cursor for use in "WHERE CURRENT OF " */
PDO_ATTR_CURSOR,/* cursor type */
PDO_ATTR_ORACLE_NULLS,/* convert empty strings to NULL */
PDO_ATTR_PERSISTENT,/* pconnect style connection */
PDO_ATTR_STATEMENT_CLASS,/* array(classname, array(ctor_args)) to specify the class of the constructed statement */
PDO_ATTR_FETCH_TABLE_NAMES, /* include table names in the column names, where available */
PDO_ATTR_FETCH_CATALOG_NAMES, /* include the catalog/db name names in the column names, where available */
PDO_ATTR_DRIVER_NAME, /* name of the driver (as used in the constructor) */
PDO_ATTR_STRINGIFY_FETCHES,/* converts integer/float types to strings during fetch */
PDO_ATTR_MAX_COLUMN_LEN,/* make database calculate maximum length of data found in a column */
PDO_ATTR_DEFAULT_FETCH_MODE, /* Set the default fetch mode */
PDO_ATTR_EMULATE_PREPARES, /* use query emulation rather than native */
/* this defines the start of the range for driver specific options.
* Drivers should define their own attribute constants beginning with this
* value. */
PDO_ATTR_DRIVER_SPECIFIC = 1000
};
注意最后的注释:
/* this defines the start of the range for driver specific options.
* Drivers should define their own attribute constants beginning with this
* value. */
我们不能去修改这个文件,而是要以 PDO_ATTR_DRIVER_SPECIFIC 为起始构造自己的枚举类型,0 到 PDO_ATTR_DRIVER_SPECIFIC 之间的值是 PHP zend 内核的保留区段
我们回到 ext/pdo_mysql 目录中,查找一下 PDO_ATTR_DRIVER_SPECIFIC,可以找到,在 php_pdo_mysql_int.h 中找到:
enum {
PDO_MYSQL_ATTR_USE_BUFFERED_QUERY = PDO_ATTR_DRIVER_SPECIFIC,
PDO_MYSQL_ATTR_LOCAL_INFILE,
PDO_MYSQL_ATTR_INIT_COMMAND,
#ifndef PDO_USE_MYSQLND
PDO_MYSQL_ATTR_READ_DEFAULT_FILE,
PDO_MYSQL_ATTR_READ_DEFAULT_GROUP,
PDO_MYSQL_ATTR_MAX_BUFFER_SIZE,
#endif
PDO_MYSQL_ATTR_COMPRESS,
PDO_MYSQL_ATTR_DIRECT_QUERY,
PDO_MYSQL_ATTR_FOUND_ROWS,
PDO_MYSQL_ATTR_IGNORE_SPACE,
PDO_MYSQL_ATTR_SSL_KEY,
PDO_MYSQL_ATTR_SSL_CERT,
PDO_MYSQL_ATTR_SSL_CA,
PDO_MYSQL_ATTR_SSL_CAPATH,
PDO_MYSQL_ATTR_SSL_CIPHER,
#if MYSQL_VERSION_ID > 50605 || defined(PDO_USE_MYSQLND)
PDO_MYSQL_ATTR_SERVER_PUBLIC_KEY
#endif
};
这里就是 PDO 自己设置的 PDO_ATTR_DRIVER_SPECIFIC 之后的枚举数据我们只需要在这里定义我们需要的枚举类型即可:
enum {
PDO_MYSQL_ATTR_USE_BUFFERED_QUERY = PDO_ATTR_DRIVER_SPECIFIC,
PDO_MYSQL_ATTR_LOCAL_INFILE,
PDO_MYSQL_ATTR_INIT_COMMAND,
#ifndef PDO_USE_MYSQLND
PDO_MYSQL_ATTR_READ_DEFAULT_FILE,
PDO_MYSQL_ATTR_READ_DEFAULT_GROUP,
PDO_MYSQL_ATTR_MAX_BUFFER_SIZE,
#endif
PDO_MYSQL_ATTR_COMPRESS,
PDO_MYSQL_ATTR_DIRECT_QUERY,
PDO_MYSQL_ATTR_FOUND_ROWS,
PDO_MYSQL_ATTR_IGNORE_SPACE,
PDO_MYSQL_ATTR_SSL_KEY,
PDO_MYSQL_ATTR_SSL_CERT,
PDO_MYSQL_ATTR_SSL_CA,
PDO_MYSQL_ATTR_SSL_CAPATH,
PDO_MYSQL_ATTR_SSL_CIPHER,
PDO_MYSQL_RW_ENV_ALL,
PDO_MYSQL_RW_ENV_CLI,
PDO_MYSQL_RW_ENV_WEB,
PDO_MYSQL_RW_ENV_NONE,
PDO_MYSQL_ATTR_RW_TIMEOUT_ENV,
PDO_MYSQL_ATTR_WRITE_TIMEOUT,
PDO_MYSQL_ATTR_READ_TIMEOUT,
#if MYSQL_VERSION_ID > 50605 || defined(PDO_USE_MYSQLND)
PDO_MYSQL_ATTR_SERVER_PUBLIC_KEY
#endif
};
这里我们添加了 7 个枚举类型:PDO_MYSQL_ATTR_READ_TIMEOUT -- 读超时
PDO_MYSQL_ATTR_WRITE_TIMEOUT -- 写超时
PDO_MYSQL_ATTR_RW_TIMEOUT_ENV -- 环境
PDO_MYSQL_ATTR_RW_TIMEOUT_ENV 这个 key 我们用来设定我们的设置在哪些环境下生效:PDO_MYSQL_RW_ENV_ALL -- 全部环境中都生效
PDO_MYSQL_RW_ENV_CLI -- 只在 cli 调用时生效
PDO_MYSQL_RW_ENV_WEB -- 只在 web 调用时生效
PDO_MYSQL_RW_ENV_NONE -- 不生效
注册枚举类型
定义枚举类型以后,我们需要向 PHP 内核注册我们用到的 key 的具体字符串值及对应的枚举类型值
在 pdo_mysql.c 中的模块初始化函数中注册我们的枚举类型及 key 值:
/* true global environment */
/* {{{ PHP_MINIT_FUNCTION
*/
static PHP_MINIT_FUNCTION(pdo_mysql)
{
REGISTER_INI_ENTRIES();
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_USE_BUFFERED_QUERY", (long)PDO_MYSQL_ATTR_USE_BUFFERED_QUERY);
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_LOCAL_INFILE", (long)PDO_MYSQL_ATTR_LOCAL_INFILE);
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_INIT_COMMAND", (long)PDO_MYSQL_ATTR_INIT_COMMAND);
#ifndef PDO_USE_MYSQLND
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_MAX_BUFFER_SIZE", (long)PDO_MYSQL_ATTR_MAX_BUFFER_SIZE);
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_READ_DEFAULT_FILE", (long)PDO_MYSQL_ATTR_READ_DEFAULT_FILE);
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_READ_DEFAULT_GROUP", (long)PDO_MYSQL_ATTR_READ_DEFAULT_GROUP);
#endif
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_COMPRESS", (long)PDO_MYSQL_ATTR_COMPRESS);
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_DIRECT_QUERY", (long)PDO_MYSQL_ATTR_DIRECT_QUERY);
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_FOUND_ROWS", (long)PDO_MYSQL_ATTR_FOUND_ROWS);
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_IGNORE_SPACE", (long)PDO_MYSQL_ATTR_IGNORE_SPACE);
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SSL_KEY", (long)PDO_MYSQL_ATTR_SSL_KEY);
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SSL_CERT", (long)PDO_MYSQL_ATTR_SSL_CERT);
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SSL_CA", (long)PDO_MYSQL_ATTR_SSL_CA);
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SSL_CAPATH", (long)PDO_MYSQL_ATTR_SSL_CAPATH);
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SSL_CIPHER", (long)PDO_MYSQL_ATTR_SSL_CIPHER);
// 注册枚举类型及对应的 KEY 值
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_RW_ENV_ALL", (long)PDO_MYSQL_RW_ENV_ALL);
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_RW_ENV_CLI", (long)PDO_MYSQL_RW_ENV_CLI);
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_RW_ENV_WEB", (long)PDO_MYSQL_RW_ENV_WEB);
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_RW_ENV_NONE", (long)PDO_MYSQL_RW_ENV_NONE);
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_RW_TIMEOUT_ENV", (long)PDO_MYSQL_ATTR_RW_TIMEOUT_ENV);
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_WRITE_TIMEOUT", (long)PDO_MYSQL_ATTR_WRITE_TIMEOUT);
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_READ_TIMEOUT", (long)PDO_MYSQL_ATTR_READ_TIMEOUT);
#if MYSQL_VERSION_ID > 50605 || defined(PDO_USE_MYSQLND)
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SERVER_PUBLIC_KEY", (long)PDO_MYSQL_ATTR_SERVER_PUBLIC_KEY);
#endif
#ifdef PDO_USE_MYSQLND
mysqlnd_reverse_api_register_api(&pdo_mysql_reverse_api TSRMLS_CC);
#endif
return php_pdo_register_driver(&pdo_mysql_driver);
}
获取传入的 value
接下来,我们需要获取调用 php 时传入的具体设置的超时时间值及限制的调用方式值,只有获取后才能实现设置
与连接超时的设置相同,我们使用 pdo 实现的 pdo_attr_lval 函数:
long write_timeout = pdo_attr_lval(driver_options, PDO_MYSQL_ATTR_WRITE_TIMEOUT, 60 TSRMLS_CC);
long read_timeout = pdo_attr_lval(driver_options, PDO_MYSQL_ATTR_READ_TIMEOUT, 60 TSRMLS_CC);
long read_write_timeout_env = pdo_attr_lval(driver_options, PDO_MYSQL_ATTR_RW_TIMEOUT_ENV, PDO_MYSQL_RW_ENV_CLI TSRMLS_CC);
判断调用方式
下面我们通过调用方式判断是否启用相应的设置
php 提供了 sapi_module.name 变量作为 cli 调用或 web 调用的标识:
int enable_read_write_timeout = 0;
//all env
if (read_write_timeout_env == PDO_MYSQL_RW_ENV_ALL) {
enable_read_write_timeout = 1;
}
// web
else if ( read_write_timeout_env == PDO_MYSQL_RW_ENV_WEB && strcmp(sapi_module.name, "cli") != 0 ) {
enable_read_write_timeout = 1;
}
// cli
else if ( read_write_timeout_env == PDO_MYSQL_RW_ENV_CLI && strcmp(sapi_module.name, "cli") == 0 ) {
enable_read_write_timeout = 1;
}
else if ( read_write_timeout_env == PDO_MYSQL_RW_ENV_NONE ) {
enable_read_write_timeout = 0;
}
设置超时时间
万事俱备,只差最后一步,设置超时时间,正如我们前面所说,这里我们使用 mysql_options 设置读写超时:
if (enable_read_write_timeout == 1) {
if (mysql_options(H->server, MYSQL_OPT_WRITE_TIMEOUT, (const char *)&write_timeout)) {
pdo_mysql_error(dbh);
goto cleanup;
}
if (mysql_options(H->server, MYSQL_OPT_READ_TIMEOUT, (const char *)&read_timeout)) {
pdo_mysql_error(dbh);
goto cleanup;
}
}
完成
重新编译 PHP 即可
php pdo mysql 超时_为 PDO 增加读写超时相关推荐
- pdo连接mysql 注入_使用PDO查询mysql避免SQL注入
使用传统的 mysql_connect .mysql_query方法来连接查询数据库时,如果过滤不严紧,就有SQL注入风险.虽然可以用mysql_real_escape_string()函数过滤用户提 ...
- php pdo mysql哪个好_php pdo和mysqli对比选择
1)总的比较 PDO MySQLi 数据库支持 12种不同的数据库支持 支持MySQL API OOP OOP + 过程 Connection Easy Easy 命名参数 支持 不支持 对象映射支持 ...
- mysql 查询语句超时_解决SQL查询总是 超时已过期
1.由于数据库设计问题造成SQL数据库新增数据时超时 症状: Microsoft OLE DB Provider for SQL Server 错误 '80040e31' ([ODBC SQL Ser ...
- pdo mysql分页_php运用PDO连接数据库,实现分页效果
PDO是一个"数据库访问抽象层",作用是统一各种数据库的访问接口,与mysql和mysqli的函数库相比,PDO让跨数据库的使用更具有亲和力:与ADODB和MDB2相比,PDO更高 ...
- 线上 mysql连接超时_线上环境数据库连接超时原因
查看线上日志发现了如下的异常: ERROR 500.jsp - Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.Com ...
- 隧道保活超时或协商超时_丰巢快递柜超时收费的法律分析
导读深圳市丰巢科技有限公司(以下简称"丰巢公司")4月末正式宣布快递柜"超时收费"办法:超过12小时之后每12小时收取5毛钱,直至3元封顶.此收费办法一经宣布便 ...
- 异步http 超时_具有CompletableFuture的异步超时
异步http 超时 有一天,我重写了执行不佳的多线程代码,该代码在Future.get()某个时刻被阻塞: public void serve() throws InterruptedExceptio ...
- java trylock超时_老师,死锁设置超时这个我知道意思,但是您能举个例子么
Java除了synchronized关键字,还提供了Lock接口,可以给我们更大的自由度.Lock lockFrom = from.getAmountLock(); Lock lockTo = to. ...
- oracle ping 超时_对于tnsping的连接超时的功能补充
tnsping,作为Oracle连接测试的一个小巧的工具,其实大家已经不陌生了,但是使用tnsping有一个问题,就是连接超时,当然这个和网络的安全策略等密不可分,但是摆在我面前的一个问题是,现在有大 ...
- pdo mysql 建库_一帖让PHP小白彻底了解PDO操作数据库的方法
php与mysql的连接有三种API接口,分别是:PHP的MySQL扩展 .PHP的mysqli扩展 .PHP数据对象(PDO) .在这三种方法中,"民间"很多是倾向于使用PDO, ...
最新文章
- 写代码可能是成为软件工程师最容易的部分
- R语言使用ggplot2包geom_jitter()函数绘制分组(strip plot,一维散点图)带状图(配置点的形状、大小)实战
- 支付宝对接3(收费问题)
- bcb 接收webservice tbytedynarray_文章推荐:基于分集接收技术的可见光接收机前端电路...
- python填充空值_Python机器学习(九十一)Pandas 填充(Imputation)空值
- NIPS’20 Spotlight | 精准建模用户兴趣,广告CTR预估准确率大幅提升!
- vs2017安装完成,但有错误。
- Nacos 新增命名空间
- 腾讯云最新10元/月有效期到2018年8月20日
- C语言基础知识梳理总结
- typora 公式对齐_Typora极简教程
- 有道云笔记设置界面 占满全屏(右侧)
- 产品经理全套入门学习资料,及各行业解析分享
- Unity3d游戏开发之C#开发(一)
- 按位取反的概念和计算方法
- cdn加速对门户网站产生的影响
- 【tips】自动化测试工具 - selenium和phantomJS
- 内存不能为“read”或written的解决
- proteus仿真出错:VCC and GND nets are connected - check net GND
- [初学笔记] matlab的 二维绘图 plot 和系列功能