分类
日记 相册

京京一岁啦

京京和妈妈
京京和妈妈

京京今天一岁啦!一支蜡烛照亮前进的道路,一只蜡烛一生一世,这是幸福之光!祝宝宝生日快乐。
今天京京还学会坐啦!棒棒的他收到了大家的许多祝福,看着他一天天长大,爸爸妈妈也有好多希望要寄语京京,祝愿宝贝岁岁更进步,年年长心知!

分类
学习笔记

MySQL Explain详解

转自 http://www.cnblogs.com/xuanzhi201111/p/4175635.html

在日常工作中,我们会有时会开慢查询去记录一些执行时间比较久的SQL语句,找出这些SQL语句并不意味着完事了,些时我们常常用到explain这个命令来查看一个这些SQL语句的执行计划,查看该SQL语句有没有使用上了索引,有没有做全表扫描,这都可以通过explain命令来查看。所以我们深入了解MySQL的基于开销的优化器,还可以获得很多可能被优化器考虑到的访问策略的细节,以及当运行SQL语句时哪种策略预计会被优化器采用。(QEP:sql生成一个执行计划query Execution plan)

mysql> explain select * from servers;
+----+-------------+---------+------+---------------+------+---------+------+------+-------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+---------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | servers | ALL  | NULL          | NULL | NULL    | NULL |    1 | NULL  |
+----+-------------+---------+------+---------------+------+---------+------+------+-------+
1 row in set (0.03 sec)
 

expain出来的信息有10列,分别是id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra,下面对这些字段出现的可能进行解释:

一、 id

     我的理解是SQL执行的顺序的标识,SQL从大到小的执行

1. id相同时,执行顺序由上至下

2. 如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行

3.id如果相同,可以认为是一组,从上往下顺序执行;在所有组中,id值越大,优先级越高,越先执行

二、select_type

      示查询中每个select子句的类型

(1) SIMPLE(简单SELECT,不使用UNION或子查询等)

(2) PRIMARY(查询中若包含任何复杂的子部分,最外层的select被标记为PRIMARY)

(3) UNION(UNION中的第二个或后面的SELECT语句)

(4) DEPENDENT UNION(UNION中的第二个或后面的SELECT语句,取决于外面的查询)

(5) UNION RESULT(UNION的结果)

(6) SUBQUERY(子查询中的第一个SELECT)

(7) DEPENDENT SUBQUERY(子查询中的第一个SELECT,取决于外面的查询)

(8) DERIVED(派生表的SELECT, FROM子句的子查询)

(9) UNCACHEABLE SUBQUERY(一个子查询的结果不能被缓存,必须重新评估外链接的第一行)

三、table

显示这一行的数据是关于哪张表的,有时不是真实的表名字,看到的是derivedx(x是个数字,我的理解是第几步执行的结果)

mysql> explain select * from (select * from ( select * from t1 where id=2602) a) b;
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| id | select_type | table      | type   | possible_keys     | key     | key_len | ref  | rows | Extra |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
|  1 | PRIMARY     | <derived2> | system | NULL              | NULL    | NULL    | NULL |    1 |       |
|  2 | DERIVED     | <derived3> | system | NULL              | NULL    | NULL    | NULL |    1 |       |
|  3 | DERIVED     | t1         | const  | PRIMARY,idx_t1_id | PRIMARY | 4       |      |    1 |       |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+复制代码

四、type

表示MySQL在表中找到所需行的方式,又称“访问类型”。

常用的类型有: ALL, index,  range, ref, eq_ref, const, system, NULL(从左到右,性能从差到好)

ALL:Full Table Scan, MySQL将遍历全表以找到匹配的行

index: Full Index Scan,index与ALL区别为index类型只遍历索引树

range:只检索给定范围的行,使用一个索引来选择行

ref: 表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值

eq_ref: 类似ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中只有一条记录匹配,简单来说,就是多表连接中使用primary key或者 unique key作为关联条件

const、system: 当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。如将主键置于where列表中,MySQL就能将该查询转换为一个常量,system是const类型的特例,当查询的表只有一行的情况下,使用system

NULL: MySQL在优化过程中分解语句,执行时甚至不用访问表或索引,例如从一个索引列里选取最小值可以通过单独索引查找完成。

五、possible_keys

指出MySQL能使用哪个索引在表中找到记录,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用

该列完全独立于EXPLAIN输出所示的表的次序。这意味着在possible_keys中的某些键实际上不能按生成的表次序使用。
如果该列是NULL,则没有相关的索引。在这种情况下,可以通过检查WHERE子句看是否它引用某些列或适合索引的列来提高你的查询性能。如果是这样,创造一个适当的索引并且再次用EXPLAIN检查查询

六、Key

key列显示MySQL实际决定使用的键(索引)

如果没有选择索引,键是NULL。要想强制MySQL使用或忽视possible_keys列中的索引,在查询中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。

七、key_len

表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度(key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的)

不损失精确性的情况下,长度越短越好 

八、ref

表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值

九、rows

 表示MySQL根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数

十、Extra

该列包含MySQL解决查询的详细信息,有以下几种情况:

Using where:列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表的全部的请求列都是同一个索引的部分的时候,表示mysql服务器将在存储引擎检索行后再进行过滤

Using temporary:表示MySQL需要使用临时表来存储结果集,常见于排序和分组查询

Using filesort:MySQL中无法利用索引完成的排序操作称为“文件排序”

Using join buffer:改值强调了在获取连接条件时没有使用索引,并且需要连接缓冲区来存储中间结果。如果出现了这个值,那应该注意,根据查询的具体情况可能需要添加索引来改进能。

Impossible where:这个值强调了where语句会导致没有符合条件的行。

Select tables optimized away:这个值意味着仅通过使用索引,优化器可能仅从聚合函数结果中返回一行

总结:
• EXPLAIN不会告诉你关于触发器、存储过程的信息或用户自定义函数对查询的影响情况
• EXPLAIN不考虑各种Cache
• EXPLAIN不能显示MySQL在执行查询时所作的优化工作
• 部分统计信息是估算的,并非精确值
• EXPALIN只能解释SELECT操作,其他操作要重写为SELECT后查看执行计划。

 

参考资料:http://dev.mysql.com/doc/refman/5.5/en/explain-output.html

                http://www.cnitblog.com/aliyiyi08/archive/2008/09/09/48878.html

                http://www.cnblogs.com/gomysql/p/3720123.html

 

分类
日记 相册

2015年奶奶生日留影

今年奶奶生日,家人齐聚长安,四世同堂,好大一个家啊。

春花再艳,总是一闪而过,夏景再绿,却只停留瞬间,相逢再美,但为何总是那么短暂啊。一年又一年,年年景不同。无论天涯海角,我们的爱彼此相连!祝老太太开心~健康~幸福晒幸福就是这样的

IMG_2674

 

分类
日记

Nginx 限制IP并发及白名单设置

如何设置能限制某个IP某一时间段的访问次数是一个让人头疼的问题,特别面对恶意的ddos攻击的时候。其中CC攻击(Challenge Collapsar)是DDOS(分布式拒绝服务)的一种,也是一种常见的网站攻击方法,攻击者通过代理服务器或者肉鸡向向受害主机不停地发大量数据包,造成对方服务器资源耗尽,一直到宕机崩溃。

cc攻击一般就是使用有限的ip数对服务器频繁发送数据来达到攻击的目的,nginx可以通过HttpLimitReqModul和HttpLimitZoneModule配置来限制ip在同一时间段的访问次数来防cc攻击。

HttpLimitReqModul用来限制连单位时间内连接数的模块,使用limit_req_zone和limit_req指令配合使用来达到限制。一旦并发连接超过指定数量,就会返回503错误。

HttpLimitConnModul用来限制单个ip的并发连接数,使用limit_zone和limit_conn指令

这两个模块的区别前一个是对一段时间内的连接数限制,后者是对同一时刻的连接数限制

HttpLimitReqModul 限制某一段时间内同一ip访问数实例

http{
    ...

    #定义一个名为allips的limit_req_zone用来存储session,大小是10M内存,
    #以$binary_remote_addr 为key,限制平均每秒的请求为20个,
    #1M能存储16000个状态,rete的值必须为整数,
    #如果限制两秒钟一个请求,可以设置成30r/m

    limit_req_zone $binary_remote_addr zone=allips:10m rate=20r/s;
    ...
    server{
        ...
        location {
            ...

            #限制每ip每秒不超过20个请求,漏桶数burst为5
            #brust的意思就是,如果第1秒、2,3,4秒请求为19个,
            #第5秒的请求为25个是被允许的。
            #但是如果你第1秒就25个请求,第2秒超过20的请求返回503错误。
            #nodelay,如果不设置该选项,严格使用平均速率限制请求数,
            #第1秒25个请求时,5个请求放到第2秒执行,
            #设置nodelay,25个请求将在第1秒执行。

            limit_req zone=allips burst=5 nodelay;
            ...
        }
        ...
    }
    ...
}

 

HttpLimitZoneModule 限制并发连接数实例

limit_zone只能定义在http作用域,limit_conn可以定义在http server location作用域

http{
    ...

    #定义一个名为one的limit_zone,大小10M内存来存储session,
    #以$binary_remote_addr 为key
    #nginx 1.18以后用limit_conn_zone替换了limit_conn
    #且只能放在http作用域
    limit_conn_zone   one  $binary_remote_addr  10m;  
    ...
    server{
        ...
        location {
            ...
           limit_conn one 20;          #连接数限制

           #带宽限制,对单个连接限数,如果一个ip两个连接,就是500x2k
           limit_rate 500k;            

            ...
        }
        ...
    }
    ...
}

nginx白名单设置

以上配置会对所有的ip都进行限制,有些时候我们不希望对搜索引擎的蜘蛛或者自己测试ip进行限制,

对于特定的白名单ip我们可以借助geo指令实现。
1.

http{
     geo $limited{
        default 1;
        #google 
        64.233.160.0/19 0;
        65.52.0.0/14 0;
        66.102.0.0/20 0;
        66.249.64.0/19 0;
        72.14.192.0/18 0;
        74.125.0.0/16 0;
        209.85.128.0/17 0;
        216.239.32.0/19 0;
        #M$
        64.4.0.0/18 0;
        157.60.0.0/16 0;
        157.54.0.0/15 0;
        157.56.0.0/14 0;
        207.46.0.0/16 0;
        207.68.192.0/20 0;
        207.68.128.0/18 0;
        #yahoo
        8.12.144.0/24 0;
        66.196.64.0/18 0;
        66.228.160.0/19 0;
        67.195.0.0/16 0;
        74.6.0.0/16 0;
        68.142.192.0/18 0;
        72.30.0.0/16 0;
        209.191.64.0/18 0;
        #My IPs
        127.0.0.1/32 0;
        123.456.0.0/28 0; #example for your server CIDR
    }

geo指令定义了一个白名单$limited变量,默认值为1,如果客户端ip在上面的范围内,$limited的值为0

2.使用map指令映射搜索引擎客户端的ip为空串,如果不是搜索引擎就显示本身真是的ip,这样搜索引擎ip就不能存到limit_req_zone内存session中,所以不会限制搜索引擎的ip访问

map $limited $limit {

1 $binary_remote_addr;

0 “”;

}

3.设置limit_req_zone和limit_req

limit_req_zone $limit zone=foo:1m rate=10r/m;

limit_req zone=foo burst=5;

以上设置完成后,可以使用pylot等压力测试方法测试并发请求。超过会返回503错误。

 

分类
日记

Centos/Ubuntu下iptables配置规则

Centos

查看iptables是否运行,查看iptable运行状态

service iptables status

清除已有规则

iptables -F
iptables -X
iptables -Z

开放端口

#允许本地回环接口(即运行本机访问本机)
iptables -A INPUT -i lo -j ACCEPT
# 允许已建立的或相关连的通行
iptables -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT
#允许所有本机向外的访问
iptables -A OUTPUT -j ACCEPT
# 允许访问22端口
iptables -A INPUT -p tcp –dport 22 -j ACCEPT
#允许访问80端口
iptables -A INPUT -p tcp –dport 80 -j ACCEPT
#允许本地访问MySQL3306端口,禁止外部访问
iptables -A INPUT -p tcp -s 127.0.0.1 –dport 3306 -j ACCEPT
iptables -A INPUT -p tcp –dport 3306 -j DROP
#允许FTP服务的21和20端口
iptables -A INPUT -p tcp –dport 21 -j ACCEPT
iptables -A INPUT -p tcp –dport 20 -j ACCEPT
#如果有其他端口的话,规则也类似,稍微修改上述语句就行
#允许ping
iptables -A INPUT -p icmp -m icmp –icmp-type 8 -j ACCEPT
#禁止其他未允许的规则访问
iptables -A INPUT -j REJECT  (注意:如果22端口未加入允许规则,SSH链接会直接断开。)
iptables -A FORWARD -j REJECT

查看已添加的iptables规则

iptables -L -n

将所有iptables以序号标记显示

iptables -L -n –line-numbers

删除INPUT里序号为3的规则

iptables -D INPUT 3

保存规则
CentOS上可能会存在安装好iptables后,iptables并不开机自启动,可以执行一下:

chkconfig –level 345 iptables on

保存

service iptables save

屏蔽IP

#如果只是想屏蔽IP的话“3、开放指定的端口”可以直接跳过。
#屏蔽单个IP的命令是
iptables -I INPUT -s 123.45.6.7 -j DROP
#封整个段即从123.0.0.1到123.255.255.254的命令
iptables -I INPUT -s 123.0.0.0/8 -j DROP
#封IP段即从123.45.0.1到123.45.255.254的命令
iptables -I INPUT -s 124.45.0.0/16 -j DROP
#封IP段即从123.45.6.1到123.45.6.254的命令是
iptables -I INPUT -s 123.45.6.0/24 -j DROP

Ubuntu

1.查看iptables列表

  1. iptables -L

如果是刚建立的服务器是没有规则的:

想查看更详细的一些信息可以用:

  1. iptables -L -v

2.入口规则
1)允许建立会话接受流量(入)

  1. iptables -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT

2)在指定端口上允许入站流量 
如果您是通过SSH来远程工作,我们先允许所有的ssh流量(默认22,如果有修改请明确端口号)入站。

  1. iptables -A INPUT -p tcp -i eth0 –dport ssh -j ACCEPT

命令解析:
-A, –append  添加一条新规则
-P, –policy 策略
-i, –in-interface
-j 参数用来指定要进行的处理动作,常用的处理动作包括:ACCEPT、REJECT、DROP、REDIRECT、MASQUERADE等
eth0 指定网卡 (一般服务器都有多个网卡)

这里如果ssh端口手动修改后,比如说是9000,命令则修改成:

  1. iptables -A INPUT -p tcp -i eth0 –dport 9000 -j ACCEPT

我们再加入一条开入网站80端口的规则试试:

  1. iptables -A INPUT -i eth0 -p tcp -m tcp –dport 80 -j ACCEPT

如果添加的开放端口很多的话也可以用一条指定来完成:

  1. iptables -A INPUT -p tcp -m multiport –dport 80,9000 -j ACCEPT

这条指定就开放了80,9000两个端口,多个端口之间用,分隔。
3)添加回环端口(loopbakc)规则 
iptables -A INPUT -i lo -j ACCEPT
4)阻断流量
iptables -A INPUT -j DROP
一旦一条规则对一个包进行了匹配,其他规则不再对这个包有效。所以我们在最后做个阻断,如果不满足上述规则就阻断。
保存:
iptables-save
3.编辑规则
在进行完上述操作后,我们看一下iptables的信息
这时我们想把第四条删掉,这里就用到了

  1. iptables -L -n –line-numbers

这个命令将所有iptables以序号标记显示
这时我们要删除Chain INPUT里序号为3的规则,执行:

  1. iptables -D INPUT 4

有删除肯定有插入啊,如果我们想在序号1后面插入一条的新的规则怎么办?
很简单,把上面的新增命令中的-A改成-I,在INPUT后面指定行号就可以了,比如:

  1. iptables -I INPUT 1 -p tcp -i eth0 –dport 1433 -j ACCEPT

4.日志
默认流量是不被记录的,如果你需要记录被丢弃的包的话,执行

  1. iptables -I INPUT 5 -m limit –limit 5/min -j LOG –log-prefix “iptables denied: ” –log-level 7

5.备份与恢复
保存您的防火墙规则到一个文件

  1. iptables-save > /etc/iptables.up.rules

设置开机自动启动
编辑/etc/network/interfaces
动态ip位置

  1. auto eth0
  2. iface eth0 inet dhcp
  3. pre-up iptables-restore < /etc/iptables.up.rules

静态ip位置

  1. auto eth0
  2. iface eth0 inet static
  3. address 8.8.8.8
  4. netmask 255.255.255.224
  5. gateway 8.8.8.4
  6. pre-up iptables-restore < /etc/iptables.up.rules
  7. auto eth1
  8. iface eth1 inet static
  9. address 192.168.1.10
  10. netmask 255.255.255.0

附:
这时我们配置完成后发现机器比外面是没法进行ping命令的。
如果需要的话须进行下列配置:
被ping:

  1. iptables -A INPUT -p icmp –icmp-type echo-request -j ACCEPT

ping别人:

  1. iptables -A OUTPUT -p icmp –icmp

注意要放到 DROP之前。