Innodb Log写入方式分析

作者/译者:王佳隆 来源: http://www.mysqlsupport.cn/ 联系方式:enjoylonely#live.cn  转载请注:译者和出处,并且不能用于商业用途,违者必究.

原文URL:http://www.mysqlperformanceblog.com/2010/07/16/analyzing-the-distribution-of-innodb-log-file-writes/

    最近我分析了一下Innodb是如何写多个日志的。我这里有个流量比较高的MySQL系统,使用的是Percona XtraDB存储引擎,

我使用strace命令分别跟踪了innodb如何去日志文件的。通常来说,innodb是以512bytes的大小来写入日志的。

关于这个可以参考:Mark Callaghan explained this and some of its performance implications 。那么innodb什么时候情况下会以大于512bytes者小于512bytes的请求写到日志里呢?

首先,我通过lsof命令找出日志的文件描述符(handle).

# lsof -p $(pidof mysqld) | grep ib_log
mysqld  29772 mysql    8uW  REG                8,2   268435456   7143989 /var/lib/mysql/ib_logfile0
mysqld  29772 mysql    9uW  REG                8,2   268435456   7143993 /var/lib/mysql/ib_logfile1

我们可以看到2个日志的handle为8和9,现在我们需要捕获innodb是如何写这2个日志的相关信息。Innodb轮循写日志就是通过这个文件描述符.

The following grabs the write sizes out of 100k calls to pwrite() and aggregates them:

# strace -f -p $(pidof mysqld) -e pwrite -s1 -xx 2>&1 \

   | grep ‘pwrite([89],’ |head -n 100000 \

   | awk ‘{writes[$5]++}END{for(w in writes){print w, ” “, writes[w]}}’

本来我可以写一个更好的脚本来捕获信息,但是下面的信息对我来说已经足够了。

bytes        count
512           44067
1024         30740
1536         15221
2048         7094
2560         1810
3072         570
3584         219
4096         112
4608         39
5120         23
5632         16
6144         15
6656         5
7168         3
7680         8
8192         2
8704         2
9216         1
9728         2
10240       1
10752       2
11264       1
11776       1
14848       1
15360       1
15872       2
16384       4
16896       4
17408       2
17920       2
18432       2
18944       8
19456       7
19968       4
20480       4
21504       1
22016       2
24064       1
40960       1

总的来说,大致有3/4是以512和1024字节写入的。那么这到底什么意思呢?这里有很多有趣的而且复杂的东西需要我们去研究。

 1. 我们可以看到,大部分的写入都小于4K。但是我们知道操作系统的page大小是4K的。如果要写入的page不在cache中,那么这个page最开始需要读出,然后再修改,最后再写回到磁盘。vadim曾经过做做一些测试,如果要性能最好,那么日志要在OS的cache中。

 2.这台MySQL的innodb_flush_log_at_trx_commit设置是2.这就说明每个事务都会有一个日志写入请求,这个和设置为1是一样的。但是如果设置成0,那么写入的方法就大不相同—这个时候写入请求会累计到一定程度,然后一起写入。

 3.那么如果说log buffer小于一个事务要写的日志大小怎么办?这是另外一个需要研究的主题了。目前我还不清楚。

4.从上面的信息来看,是否可以很容易知道log buffer大小应该给多少呢?最大的写入小于40K,这好像可以说明分配64K给log buffer就已经足够了。这是真的吗?我们需要去测试才可以知道。peter以前和我谈过这个问题,log buffer背后的机制其实是很复杂的,到底log buffer需要保留多少空间给写操作。这些都需要更深入的研究。但是有一点可以确认,即使最大的写入操作不是很大的情况下,如果log buffer设置太小,性能肯定是不好的,而且会造成而外的锁。这个问题或许我们同样需要去研究。

最后,研究innodb是如何写日志的很容易,但是事实上innodb redo log机制是很复杂的,有时候我们很难说去猜想应该是什么样的,而应该去更深入的研究才可以知道的更多。也许我们可以按照上面这种步骤去研究不同LOG buufer大小,不同的日志参数设置,以及不同的服务器负载的情况下innodb到底是如何来写入日志的。

参考地址:http://mysqlha.blogspot.com/2009/06/buffered-versus-direct-io-for-innodb.html

Linux运维Tips(-)

        作者:吴炳锡 来源:http://www.mysqlsupport.cn/ 联系方式: wubingxi#gmail.com 转载请注:译者和出处,并且不能用于商业用途,违者必究.

       对于一个Linux运维团队,在管理一些机器时,难免会出现一些尴嘎的事情,A同事在操作的时间,B同事也上去操作了;本来工作时间上去时,如果看一下磁盘使用状态,也许就必免了假日收到了短信报警。对于这些问题怎么处理呢?

      聪明的朋友说,登录到系统后运行一下w 和df -h不就行了。是的,这是一个很好的解决方法。但人总是懒惰的。要不,也不会出那么事了。

        这里提供一个自动化每一个用户登录上去,自动把df  -h 和w的结果输出到终端。实现方法: 编辑~/.profile 或是 ~/.bashrc (提倡改.profile)在最后添加:

echo "============================="

df -h

echo "============================="

w

       然后再登录到系统中时就会自动显示:

=============================

Filesystem            Size  Used Avail Use% Mounted on

/dev/sda2             3.9G  2.4G  1.4G  65% /

/dev/sda1             122M   12M  104M  11% /boot

tmpfs                 250M     0  250M   0% /dev/shm

/dev/sdb1           11G  1.9G  9.1G  17% /data

=============================

 09:15:00 up 28 days, 20 min,  1 user,  load average: 0.00, 0.00, 0.00

USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
wubx     pts/0    10.10.15.72      09:15    0.00s  0.02s  0.02s -bash

利用tcpflow抓取SQL

作者:吴炳锡 来源:http://www.mysqlsupport.cn/ 联系方式: wubingxi#gmail.com 转载请注:译者和出处,并且不能用于商业用途,违者必究.

以前介绍过利用tcpdump抓取相关的SQL,但是在识别方面并不友好,只是能看到相关的SQL。今天推荐一个强劲的工具:tcpflow加一些牛人们开发的工具从而实现友好的显示相关的SQL。
相关工具下载,功先欲其事,必先利其器:
Tcpflow 下载:http://www.circlemud.org/~jelson/software/tcpflow/
extract_queries.: http://mysqldump.azundris.com/uploads/extract_queries.c
使用方法:
#mkdir flow
#cd flow
#tcpflow –i eth0 dst MasterIP and port 3306
等待一会 Ctrl+c

#cd ..
# find flow –print0 |xargs -0 extract_queries –u >slow
#mysqldumpslow -s c slow >stats

不足之处:
不能真正把SQL的执行时间记录下来,因为这个只是网络IO的流量抓取,同时这个也不能把真正的连接数据库的用户抓下来。
原文地址:http://mysqldump.azundris.com/archives/85-Getting-SQL-from-a-SPAN-port.html

Linux 安装pptp vpn client

作者:吴炳锡 来源:http://www.mysqlsupport.cn/ 联系方式: wubingxi#gmail.com 转载请注:译者和出处,并且不能用于商业用途,违者必究.

    Linux使用pptp vpn client 其实很简单的,只是相对文档较少或是落后造成很多Linuxer报怨。下面我简单的列一下操作步骤。

背景:
    系统使用Redhat Enterprise 5.4(CentOS也支持)
    该文档应该能适应不同的Linux。
    基于命令行的操作。我的开发机器上没装图形界面。

需要软件:
     pptp 该软件可以从:
     http://pptpclient.sourceforge.net/#download
     pppd 一般系统自带。

安装:
      下载pptp,下载相应的pptp的RPM包即可。
      rpm -ivh pptp-*.rpm
      这样基本上完成了50%的工作了。
配置:   
     pptp安装后有一个配置命令:pptpsetup

# pptpsetup –help

pptpsetup –create <TUNNEL> –server <SERVER> [–domain <DOMAIN>]

          –username <USERNAME> [–password <PASSWORD>]

          [–encrypt] [–start]

 

pptpsetup –delete <TUNNEL>

Options:
* <TUNNEL>  配置文件的名称,可以根据不同的连接用不同的名字,自已指定,我这里有vpn.
* <SERVER>  PPTP SERVER的IP。
* <DOMAIN> 所在的域,可以省略,一般不用。
* <USERNAME>  VPN 上认证用的用户名,VPN用户
* <PASSWORD>  VPN上用户认证用的密码
* –encrypt 启用加密
*           当没使用–encrypt 连接时出现下面的错误时,表示使用了加密,这点也可以和VPN的管理员联系确认一下,遇到下面的*           情况可以加上该参数。
*                    CHAP authentication succeeded
*                          LCP terminated by peer (ZM-76-^@<M-Mt^@^@^BM-f
*                            
* –start  直接连接,第一次使用。

创建配置文件

假设VPN的用户名和密码都是wubx,IP是:xxx.xxx.xxx.xx

#pptpsetup –create vpn –server XXX.XXX.XXX.XX  –username wubx –password wubx –encrypt –start

         运气好了,就可以看到连接成功的信息了。
    如:

Using interface ppp0

Connect: ppp0 <–> /dev/pts/2

CHAP authentication succeeded

MPPE 128-bit stateless compression enabled

local  IP address 192.168.111.103

remote IP address 192.168.111.100

以后的启动可以使用:

pppd call vpn

相应的LOG也可以在/var/log/message中查看。

然后可以利用route命令添加相应的路由:
如我这边VPN的机器所在网段是192.168.110.0/24 那么我就可以使用:

#route add -net  192.168.110.0 netmask 255.255.255.0  gw 192.168.112.100 device ppp0

添加完路由就可以使用了。

备注:

建立连接:    

对于以后VPN的启动可以写一个ppp-on 放到/usr/local/bin内容:
#!/bin/bash

exec /usr/sbin/pppd call vpn

关闭连接:

可以写一个ppp-off放到/usr/local/bin/下,内容如下:

#!/bin/bash

if [ “$1” = “” ]; then

        DEVICE=ppp0

else

        DEVICE=$1

fi

if [ -r /var/run/$DEVICE.pid ]; then

        kill -INT `cat /var/run/$DEVICE.pid`

        if [ !”$?” = “0” ]; then

                rm -rf /var/run/$DEVICE.pid

                echo “ERROR: Removed stale pid file”

                exit 1

        fi

echo “PPP link to $DEVICE terminated.”

exit 0

fi

echo “ERROR: PPP link is not active on $DEVICE”

exit 1

路由添加:

         可以写到/etc/ppp/ip-up中:

         在exit 0前添加:

route add -net  192.168.110.0 netmask 255.255.255.0  gw 192.168.112.100 device ppp0

具体参考:
  PPP-HOWTO  http://man.chinaunix.net/linux/how/PPP-HOWTO.html#toc15

MegaCli 学习 及R710 可选Raid卡分类

    作者:吴炳锡 来源:http://www.mysqlsupport.cn/ 联系方式: wubingxi#gmail.com 转载请注明作/译者和出处,并且不能用于商业用途,违者必究.

MegaCli常用参数介绍
MegaCli -adpCount 【显示适配器个数】
MegaCli -AdpGetTime –aALL 【显示适配器时间】
MegaCli -AdpAllInfo -aAll     【显示所有适配器信息】
MegaCli -LDInfo -LALL -aAll    【显示所有逻辑磁盘组信息】
MegaCli -PDList -aAll    【显示所有的物理信息】
MegaCli -AdpBbuCmd -GetBbuStatus -aALL |grep ‘Charger Status’ 【查看充电状态】
MegaCli -AdpBbuCmd -GetBbuStatus -aALL【显示BBU状态信息】
MegaCli -AdpBbuCmd -GetBbuCapacityInfo -aALL【显示BBU容量信息】
MegaCli -AdpBbuCmd -GetBbuDesignInfo -aALL    【显示BBU设计参数】
MegaCli -AdpBbuCmd -GetBbuProperties -aALL    【显示当前BBU属性】
MegaCli -cfgdsply -aALL    【显示Raid卡型号,Raid设置,Disk相关信息】
MegaCli -cfgdsply -aALL |grep Policy      【查看Cache 策略设置】
MegaCli -AdpBbuCmd -GetBbuStatus -aALL |grep ‘Relative State of Charge’【查看充电进度百分比】
磁带状态的变化,从拔盘,到插盘的过程中。
Device         |Normal|Damage|Rebuild|Normal
Virtual Drive     |Optimal|Degraded|Degraded|Optimal
Physical Drive     |Online|Failed –> Unconfigured|Rebuild|Online

R710 可选Raid卡分类

内部:
PERC H200(6 Gb/秒)
PERC H700(6 Gb/秒),配备512 MB电池后备高速缓存
SAS 6/iR
PERC 6/i,配备256 MB电池后备高速缓存
PERC S100(基于软件)
PERC S300(基于软件)
外部:
PERC H800(6 Gb/秒),配备512 MB电池后备高速缓存
PERC 6/E,配备256 MB或512 MB电池后备高速缓存
外部HBA(非RAID):
SAS 5/E HBA
LSI2032 PCIe SCSI HBA

Linux服务器基本安装

作者:吴炳锡 来源:http://www.mysqlsupport.cn/ 联系方式: wubingxi#gmail.com 转载请注明作/译者和出处,并且不能用于商业用途,违者必究。

  该文档只用于一般服务器的安装,其它专用服务器安装仅供参考。

系统安装步骤:
1)输入linux text选择text安装模式。
2)安装时语言环境选English。
3)键盘类型选us。
4)鼠标选择No-mouse。
5)安装类型选Custom。
6)分区设置为:
/dev/sda
/dev/sda1 512M ext3 /boot
/dev/sda2 5G ext3 /home
/dev/sda3 3G ext3 /
/dev/sda4 Extended
/dev/sda5 5G ext3 /var
/dev/sda6 2G ext3 swap
/dev/sda7 余空间 /data
7)使用GRUB Boot loader。
8)不增加参数在Boot Loader Configuration。
9)不为Boot Loader设置密码。
10)设置Boot Loader启动Linux。
11)将Boot Loader安装在硬盘的MBR。
12)网络设置,按分配的IP配置网卡。
/etc/sysconfig/network-scripts/
#ls ifcfg-*
ifcfg-eth0 ifcfg-eth1 ifcfg-lo
编辑相应文件
/sbin/service network restart

13)主机名称视情况而定,预定为WEB-数字,数字为IP最后3位。
14)防火墙的安全级别设为No firewall,禁用SEClinux
15)语言支持选English (USA) 和Chinese (P.R. of China)。
16)默认语言为English (USA)。
17)时区选Asia/Shanghai。
18)Root Password为:redhat
19)Authentication Configuration启用Use Shadow Passwords和Enable MD5 Passwords。
20)Package Group选择:
@ Editors
@ Text-based Internet
@ Server Configuration Tools
@ Development Tools
@ Kernel Development
@ Administration Tools
@ System Tools
21)不必创建Boot Diskette。
22)配置显示选项,指定启动时进入文本模式。
OS安装完毕。

安装后配置
1) 禁用ssh1登录
vi /etc/ssh/sshd_config
#Port 22
#Protocol 2,1
修改为
Port 22
Protocol 2
2) 禁用多于服务
rm /etc/rc.d/rc3.d/* -rf

chkconfig network on
chkconfig rsync on

chkconfig sshd on
chkconfig syslog on
chkconfig crond on
chkconfig xinetd on

根据需要加入自已的相应服务。
3)限制登录IP
vi /etc/hosts.allow
加入
all:IP.:allow
all:all:deny
IP为允许进入管理的IP。当然这个文件也可以不用。
4)定时同步时间
crontab -e
加入
0 0 * * * rdate -s time-a.nist.gov
or
10 03 * * * /usr/sbin/ntpdate -u tick.ucla.edu tock.gpsclock.com ntp.nasa.gov timekeeper.isi.edu usno.pa-x.dec.com
5)关闭ipv6
echo “alias net-pf-10 off” >> /etc/modprobe.conf.dist

drupal转worldpress

作者:吴炳锡 来源:http://www.mysqlsupport.cn/ 联系方式:select unhex(’777562696E67786940676D61696C2E636F6D’); 载请注明作/译者和出处,并且不能用于商业用途,违者必究。

用Drupal太灵活了,灵活的我都搞不定了。所以我投向了worldpress.对比了一下表结构。参考网上的说明搞出了:

use support;
delete from wp_posts;    
delete from wp_comments;

# posts
INSERT INTO
    wp_posts (id, post_date, post_content, post_title,
    post_excerpt, post_name, post_modified)
SELECT DISTINCT
    n.nid, FROM_UNIXTIME(created), body, n.title,
    teaser,
    REPLACE(REPLACE(REPLACE(REPLACE(LOWER(n.title),’ ‘, ‘_’),’.’, ‘_’),’,’, ‘_’),’+’, ‘_’),
    FROM_UNIXTIME(changed)
FROM  drupal_bak.node n, drupal_bak.node_revisions r
WHERE n.vid = r.vid;

# comments
INSERT INTO
    wp_comments
    (comment_post_ID, comment_date, comment_content, comment_parent, comment_author, comment_author_email, comment_author_url)
SELECT
    nid, FROM_UNIXTIME(timestamp),
    comment, thread, name, mail, homepage
FROM drupal_bak.comments ;

# update comments count on wp_posts table
UPDATE `wp_posts` SET `comment_count` = (SELECT COUNT(`comment_post_id`) FROM `wp_comments` WHERE `wp_posts`.`id` = `wp_comments`.`comment_post_id`);

# fix post slugs. first we have to remove the duplicate _____ chars, then replace that with a single – char
UPDATE wp_posts set post_name = REPLACE(post_name, ‘__’, ‘_’);
UPDATE wp_posts set post_name = REPLACE(post_name, ‘__’, ‘_’);
UPDATE wp_posts set post_name = REPLACE(post_name, ‘__’, ‘_’);
UPDATE wp_posts set post_name = REPLACE(post_name, ‘__’, ‘_’);
UPDATE wp_posts set post_name = REPLACE(post_name, ‘_’, ‘-‘);

 

然后就可以看到worldpress工作了。

记录:基于连接的DDOS攻击防范

遇到攻击。
采取措施:
做了DNS负载均衡,一个域名指向多台机器(负载均衡器的Session已经经分配较慢)
加入:

net.ipv4.tcp_synack_retries=3
net.ipv4.tcp_syn_retries=3
net.ipv4.tcp_max_syn_backlog=2048
net.ipv4.tcp_syncookies=1

封超过100个连接的IP:

#!/bin/sh
/bin/netstat -na|grep ESTABLISHED|awk ‘{print $5}’|awk -F: ‘{print $1}’|sort|uniq -c|sort -rn|grep -v -E ‘172.16|127.0’|awk ‘{if ($2!=null && $1>100) {print $2}}’>/tmp/dropip
for i in $(cat /tmp/dropip)
do
/sbin/iptables -I INPUT  -p tcp -m tcp -s $i –dport 80 –syn -j REJECT
echo “$i kill at `date`”>>~river/ddos
done

 

最终效果还是不明显,IP变化太大。

今天继续找找别的方法。

用Tcpdump抓取MySQL执行的SQL

#!/bin/bash
tcpdump -i eth0 -s 0 -l -w – dst port 3306 | strings | perl -e ‘
#!/bin/bash
while(<>) { chomp; next if /^[^ ]+[ ]*$/;
if(/^(SELECT|UPDATE|DELETE|INSERT|SET|COMMIT|ROLLBACK|CREATE|DROP|ALTER|CALL)/i) {
if (defined $q) { print “$q\n”; }
$q=$_;
} else {
$_ =~ s/^[ \t]+//; $q.=” $_”;
}
}’

memcache内部key的需取出

作者:吴炳锡 来源:http://www.mysqlsupport.cn/ 转载请注明作/译者和出处,并且不能用于商业用途,违者必究。

memcache 查看状态支持的命令:
[code]

1. stats
2. stats reset
3. stats malloc
4. stats maps
5. stats sizes
6. stats slabs
7. stats items
8. stats cachedump slab_id limit_num
9. stats detail [onoffdump]

[/code]

执行stats cachedump 3 0命令。这里的3表示上面图中items后面的数字,0标示显示全部的数据,如果是1就标示只显示1条。

一个例程:
[code]


1.
2. $host=’192.168.15.225′;
3. $port=11211;
4. $mem=new Memcache();
5. $mem->connect($host,$port);
6. $items=$mem->getExtendedStats (‘items’);
7. $items=$items[“$host:$port”][‘items’];
8. for($i=0,$len=count($items);$i<$len;$i++){
9. $number=$items[$i][‘number’];
10. $str=$mem->getExtendedStats (“cachedump”,$number,0);
11. $line=$str[“$host:$port”];
12. if( is_array($line) && count($line)>0){
13. foreach($line as $key=>$value){
14. echo $key.’=>’;
15. print_r($mem->get($key));
16. echo “\r\n”;
17. }
18. }
19. }
20. ?>
[/code]