标签 MySql 下的文章

PHP 超时和http状态处理

首先是PHP的mysql的链接方式:

PHP与MySQL的连接有三种API接口,分别是:PHP的MySQL扩展 、PHP的mysqli扩展 、PHP数据对象(PDO) ,下面针对以上三种连接方式做下总结,以备在不同场景下选出最优方案。

PHP的MySQL扩展是设计开发允许php应用与MySQL数据库交互的早期扩展。MySQL扩展提供了一个面向过程的接口,并且是针对MySQL4.1.3或者更早版本设计的。因此这个扩展虽然可以与MySQL4.1.3或更新的数据库服务端进行交互,但并不支持后期MySQL服务端提供的一些特性。由于太古老,又不安全,所以已被后来的mysqli完全取代;

PHP的mysqli扩展,我们有时称之为MySQL增强扩展,可以用于使用 MySQL4.1.3或更新版本中新的高级特性。其特点为:面向对象接口 、prepared语句支持、多语句执行支持、事务支持 、增强的调试能力、嵌入式服务支持 、预处理方式完全解决了sql注入的问题。不过其也有缺点,就是只支持mysql数据库。如果你要是不操作其他的数据库,这无疑是最好的选择。

PDO是PHP Data Objects的缩写,是PHP应用中的一个数据库抽象层规范。PDO提供了一个统一的API接口可以使得你的PHP应用不去关心具体要连接的数据库服务器系统类型,也就是说,如果你使用PDO的API,可以在任何需要的时候无缝切换数据库服务器,比如从Oracle 到MySQL,仅仅需要修改很少的PHP代码。其功能类似于JDBC、ODBC、DBI之类接口。同样,其也解决了sql注入问题,有很好的安全性。不过他也有缺点,某些多语句执行查询不支持(不过该情况很少)。

官文对于三者之间也做了列表性的比较:
20180815163422.jpg

PDO设置超时和持久化链接的方法:

    PDO::ATTR_CASE              => PDO::CASE_NATURAL, //大小写
    PDO::ATTR_ERRMODE           => PDO::ERRMODE_EXCEPTION,//错误处理
    PDO::ATTR_ORACLE_NULLS      => PDO::NULL_NATURAL,//空转换为mysql的 null
    PDO::ATTR_STRINGIFY_FETCHES => false, //字符类型转换
    PDO::ATTR_EMULATE_PREPARES  => false,
    PDO::ATTR_TIMEOUT => 30,//链接超时时间
    PDO::ATTR_PERSISTENT => true //持久化链接

查询mysql设置的各种超时参数:show global variables like “%timeout%”;
PHP高版本对mysql扩展操作php已经不在进行维护,会出现各种问题,链接阻塞等.


PHP的fast-cgi配置:

p

m = dynamic #对于专用服务器,pm可以设置为static。 #如何控制子进程,选项有static和dynamic。如果选择static,则由pm.max_children指定固定的子进程数。
如果选择dynamic,则由下开参数决定: 
pm.max_children #,子进程最大数 
pm.start_servers #,启动时的进程数 
pm.min_spare_servers #,保证空闲进程数最小值,如果空闲进程小于此值,则创建新的子进程               pm.max_spare_servers #,保证空闲进程数最大值,如果空闲进程大于此值,此进行清理 
pm.max_requests = 1000 #设置每个子进程重生之前服务的请求数. 对于可能存在内存泄漏的第三方模块来说是非常有用的. 如果设置为 ’0′ 则一直接受请求. 等同于 PHP_FCGI_MAX_REQUESTS 环境变量. 默认值: 0. 

下面4个参数的意思分别为: 
pm.max_children:静态方式下开启的php-fpm进程数量 
pm.start_servers:动态方式下的起始php-fpm进程数量 
pm.min_spare_servers:动态方式下的最小php-fpm进程数 
pm.max_spare_servers:动态方式下的最大php-fpm进程数量 
区别: 
如果dm设置为 static,那么其实只有pm.max_children这个参数生效。系统会开启设置数量的php-fpm进程。
如果dm设置为 dynamic,那么pm.max_children参数失效,后面3个参数生效。 
系统会在php-fpm运行开始 的时候启动pm.start_servers个php-fpm进程, 然后根据系统的需求动态在pm.min_spare_servers和pm.max_spare_servers之间调整php-fpm进程数 

根据自己的服务器进行进程优化,启动个数不宜太大或者太小.

php + nginx 做反向代理设置:

fastcgi_connct_timeout 60

Nginx和fastcgi进程建立连接的超时时间,默认60秒,如果超过了这个时间就断开连接。

fastcgi_read_timeout 300

和fastcgi进程建立连接后获得fastcgi进程响应的超时时间,默认60秒,如果超过了这个时间都没有获得响应就断开连接。我们经常碰到的是'504 Gateway Time-out',就是因为后端连接没有在超时时间内返回数据导致的。我们经常碰到的是'502 Bad Gateway',是因为fastcig进程报错,导致连接断开。

fastcgi_send_timeout 300

Nginx向fastcgi进程发送请求的超时时间,默认60秒,如果超过了这个时间都没有发送完就断开连接。可以通过上传比较大的文件,就会出现超时,然后就会返回'504 Gateway Time-out'。

php之 curl :

curl_setopt($ch,opt)可以设置一些超时的设置
主要包括: *(重要)CURLOPT_TIMEOUT设置cURL允许执行的最长秒数。 
          *(重要)CURLOPT_TIMEOUT_MS设置cURL允许执行的最长毫秒数。(在cURL7.16.2中被加入。从PHP5.2.3起可使用。) 
          CURLOPT_CONNECTTIMEOUT在发起连接前等待的时间,如果设置为0,则无限等待。 
          CURLOPT_CONNECTTIMEOUT_MS尝试连接等待的时间,以毫秒为单位。如果设置为0,则无限等待。在cURL7.16.2中被加入。从PHP5.2.3开始可用。 
          CURLOPT_DNS_CACHE_TIMEOUT设置在内存中保存DNS信息的时间,默认为120秒。 

php 流:
那么如何设置超时呢,PHP 流机制可以通过 default_socket_timeout 指令来配置。
流是 PHP 中很重要的一个特性,以后可以说一说,简单的理解就是在 PHP 中,不管是读取磁盘文件、HTTP 接口,都可以认为是一种流(socket/stream)。

说明下, socket/stream 的等待时间是不包括在 PHP 最大执行时间内的。
比如说在 PHP.ini 中 配置 max_execution_time = 30,max_execution_time = 20,那么这个 PHP 程序最大处理执行时间是 50 秒。

现在重点来了,原来自己认为超时时间假如为 m 秒,那么访问接口最终响应(包括网络传输时间)超过 m 秒,调用程序就会报错。实际并不是这样,只要在 m 秒数据包一直在传输,那么调用程序就不会报错。

Mysql NULL 和 ''

陷阱一:空值不一定为空

  空值是一个比较特殊的字段。在MySQL数据库中,在不同的情形下,空值往往代表不同的含义。这是MySQL数据库的一种特性。如在普通的字段中(字符型的数据),空值就是表示空值。但是如果将一个空值的数据插入到TimesTamp类型的字段中,空值就不一定为空。此时为出现什么情况呢

  我先创建了一个表。在这个表中有两个字段:User_id(其数据类型是int)、Date(其数据类型是TimesTamp)。现在往这个表中插入一条记录,其中往Date字段中插入的是一个NULL空值。可是当我们查询时,其结果显示的却是插入记录的当前时间。这是怎么一回事呢?其实这就是在MySQL数据库中执行SQL语句时经常会遇到的一个陷阱:空值不一定为空。在操作时,明明插入的是一个空值的数据,但是最后查询得到的却不是一个空值。

  在MySQL数据库中,NULL对于一些特殊类型的列来说,其代表了一种特殊的含义,而不仅仅是一个空值。对于这些特殊类型的列,各位读者主要是要记住两个。一个就是笔者上面举的TimesTamp数据类型。如果往这个数据类型的列中插入Null值,则其代表的就是系统的当前时间。另外一个是具有auto_increment属性的列。如果往这属性的列中插入Null值的话,则系统会插入一个正整数序列。而如果在其他数据类型中,如字符型数据的列中插入Null的数据,则其插入的就是一个空值。

  陷阱二:空值不一定等于空字符

  在MySQL中,空值(Null)与空字符(’’)相同吗?答案是否定的。

  在同一个数据库表中,同时插入一个Null值的数据和一个’’空字符的数据,然后利用Select语句进行查询。显然其显示的结果是不相同的。从这个结果中就可以看出,空值不等于空字符。这就是在MySQL中执行SQL语句遇到的第二个陷阱。在实际工作中,空值数据与空字符往往表示不同的含义。数据库管理员可以根据实际的需要来进行选择。如对于电话号码等字段,可以默认设置为空值(表示根本不知道对方的电话号码)或者设置为空字符(表示后来取消了这个号码)等等。由于他们在数据库中会有不同的表现形式,所以数据库管理员需要区别对待。笔者更加喜欢使用空值,而不是空字符。这主要是因为针对空值这个数据类型有几个比较特殊的运算字符。如果某个字段是空字符,数据库中是利用字段名称来代替。相反,如果插入的是空值,则直接显示的是NULL。这跟其他数据库的显示方式也是不同的。

  一是IS NULL 和IS NOT NULL关键字。如果要判断某个字段是否含用空值的数据,需要使用特殊的关键字。其中前者表示这个字段为空,后者表示这个字段为非空。在Select语句的查询条件中这两个关键字非常的有用。如需要查询所有电话号码为空的用户(需要他们补充电话号码信息),就可以在查询条件中加入is not null关键字。

  二是Count等统计函数,在空值上也有特殊的应用。如现在需要统计用户信息表中有电话号码的用户数量,此时就可以使用count函数、同时将电话号码作为参数来使用。因为在统计过程中,这个函数会自动忽略空值的数据。此时统计出来的就是有电话号码的用户信息。如果采用的是空字符的数据,则这个函数会将其统计进去。统计刚才建立的两条记录时,系统统计的结果是1,而不是2。可见系统自动将Null值的数据忽略掉了。

判断NULL用is null 或者 is not null。 sql语句里可以用ifnull函数来处理
判断空字符串‘’,要用 ='' 或者 <>''。sql语句里可以用if(col,col,0)处理,即:当col为true时(非null,及非'')显示,否则打印0

来至某一处:
首先,我们要搞清楚“空值” 和 “NULL” 的概念:
1、空值是不占用空间的
2、mysql中的NULL其实是占用空间的,下面是来自于MYSQL官方的解释
“NULL columns require additional space in the row to record whether their values are NULL. For MyISAM tables, each NULL column takes one bit extra, rounded up to the nearest byte.”
PS:打个比方来说,你有一个杯子,空值代表杯子是真空的,NULL代表杯子中装满了空气,虽然杯子看起来都是空的,但是区别是很大的。