定义枚举类型

首先,我们先要创建枚举类型,也就是未来在 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 增加读写超时相关推荐

  1. pdo连接mysql 注入_使用PDO查询mysql避免SQL注入

    使用传统的 mysql_connect .mysql_query方法来连接查询数据库时,如果过滤不严紧,就有SQL注入风险.虽然可以用mysql_real_escape_string()函数过滤用户提 ...

  2. php pdo mysql哪个好_php pdo和mysqli对比选择

    1)总的比较 PDO MySQLi 数据库支持 12种不同的数据库支持 支持MySQL API OOP OOP + 过程 Connection Easy Easy 命名参数 支持 不支持 对象映射支持 ...

  3. mysql 查询语句超时_解决SQL查询总是 超时已过期

    1.由于数据库设计问题造成SQL数据库新增数据时超时 症状: Microsoft OLE DB Provider for SQL Server 错误 '80040e31' ([ODBC SQL Ser ...

  4. pdo mysql分页_php运用PDO连接数据库,实现分页效果

    PDO是一个"数据库访问抽象层",作用是统一各种数据库的访问接口,与mysql和mysqli的函数库相比,PDO让跨数据库的使用更具有亲和力:与ADODB和MDB2相比,PDO更高 ...

  5. 线上 mysql连接超时_线上环境数据库连接超时原因

    查看线上日志发现了如下的异常: ERROR 500.jsp - Error querying database.  Cause: com.mysql.jdbc.exceptions.jdbc4.Com ...

  6. 隧道保活超时或协商超时_丰巢快递柜超时收费的法律分析

    导读深圳市丰巢科技有限公司(以下简称"丰巢公司")4月末正式宣布快递柜"超时收费"办法:超过12小时之后每12小时收取5毛钱,直至3元封顶.此收费办法一经宣布便 ...

  7. 异步http 超时_具有CompletableFuture的异步超时

    异步http 超时 有一天,我重写了执行不佳的多线程代码,该代码在Future.get()某个时刻被阻塞: public void serve() throws InterruptedExceptio ...

  8. java trylock超时_老师,死锁设置超时这个我知道意思,但是您能举个例子么

    Java除了synchronized关键字,还提供了Lock接口,可以给我们更大的自由度.Lock lockFrom = from.getAmountLock(); Lock lockTo = to. ...

  9. oracle ping 超时_对于tnsping的连接超时的功能补充

    tnsping,作为Oracle连接测试的一个小巧的工具,其实大家已经不陌生了,但是使用tnsping有一个问题,就是连接超时,当然这个和网络的安全策略等密不可分,但是摆在我面前的一个问题是,现在有大 ...

  10. pdo mysql 建库_一帖让PHP小白彻底了解PDO操作数据库的方法

    php与mysql的连接有三种API接口,分别是:PHP的MySQL扩展 .PHP的mysqli扩展 .PHP数据对象(PDO) .在这三种方法中,"民间"很多是倾向于使用PDO, ...

最新文章

  1. 写代码可能是成为软件工程师最容易的部分
  2. R语言使用ggplot2包geom_jitter()函数绘制分组(strip plot,一维散点图)带状图(配置点的形状、大小)实战
  3. 支付宝对接3(收费问题)
  4. bcb 接收webservice tbytedynarray_文章推荐:基于分集接收技术的可见光接收机前端电路...
  5. python填充空值_Python机器学习(九十一)Pandas 填充(Imputation)空值
  6. NIPS’20 Spotlight | 精准建模用户兴趣,广告CTR预估准确率大幅提升!
  7. vs2017安装完成,但有错误。
  8. Nacos 新增命名空间
  9. 腾讯云最新10元/月有效期到2018年8月20日
  10. C语言基础知识梳理总结
  11. typora 公式对齐_Typora极简教程
  12. 有道云笔记设置界面 占满全屏(右侧)
  13. 产品经理全套入门学习资料,及各行业解析分享
  14. Unity3d游戏开发之C#开发(一)
  15. 按位取反的概念和计算方法
  16. cdn加速对门户网站产生的影响
  17. 【tips】自动化测试工具 - selenium和phantomJS
  18. 内存不能为“read”或written的解决
  19. proteus仿真出错:VCC and GND nets are connected - check net GND
  20. [初学笔记] matlab的 二维绘图 plot 和系列功能

热门文章

  1. [已解决]smallbin double linked list
  2. php入门,windows安装与环境配置,基础语法学习
  3. transition动画无效 iphone6
  4. 参加西湖论剑2021
  5. 基频和倍频的概念_基频峰,泛频峰,倍频峰,二倍频峰的区别
  6. Mybatis复习1——B站
  7. Linux网页版操作
  8. 微信App iOS客户端不同阶段的发展策略
  9. Android 打造任意层级树形控件 考验你的数据结构和设计
  10. 申宝股票-三大指数震荡下行