mysqld 配置优化,请一定要加 skip-name-resolve,否则将被show processlist 里的 unauthenticated user 搞死

把mysql迁移到单独的服务器,与web服务器分离;但似乎不怎么稳定,经常无法连接,报错是连接数过多;登录到服务器上命令行连接也是无法连接。这情况很频繁,今天竟然出现了两次。之前一直是重启mysql解决问题,但如此频繁的故障,就有十分的必要去查找原因了。

在服务器上命令行登录,mysql -uroot -upassword,把密码写到命令行里,不用每次再输入,按ctrl+p 然后回车,尝试N次,终于登录进去了;连接数过多,终究还是可以找到空子进去的。赶快查看并保留运行状态的重要参数:

show variables;
show status;

show processlist;

好家伙,这么多连接:

| 10520 | unauthenticated user | 192.168.0.109:41063 | NULL  | Connect | NULL | login | NULL             |
| 10521 | unauthenticated user | 192.168.0.109:41065 | NULL  | Connect | NULL | login | NULL             |
| 10522 | unauthenticated user | 192.168.0.109:41067 | NULL  | Connect | NULL | login | NULL             |
| 10523 | unauthenticated user | 192.168.0.109:41068 | NULL  | Connect | NULL | login | NULL             |
| 10524 | unauthenticated user | 192.168.0.109:41069 | NULL  | Connect | NULL | login | NULL             |
| 10525 | unauthenticated user | 192.168.0.109:41070 | NULL  | Connect | NULL | login | NULL             |
| 10526 | unauthenticated user | 192.168.0.109:41071 | NULL  | Connect | NULL | login | NULL             |

如些上千行。先不管,这里肯定是问题突破口。

set global max_connections=4000;

增加允许的最大连接数,先让前台网站可以正常工作。

回过头google :mysql unauthenticated user

果然,遇到此类问题的人很多,问题在于mysql的反向ip地址解析,配置参数里加上skip-name-resolve就可以。

总结一下原因,大概如下:

因为mysql默认会根据客户端的ip地址反向解析,用于用户登录授权之用。不过正常情况下,很少会有人这样用。ip地址反向解析是很慢的,尤其是高负荷的mysql,每秒种几百次甚至更高的请求,这个请求压到本地的dns服务器上,dns服务器说不定会怀疑你在恶意请求,然后不理你了,然后这些登录请求就挂在那里,后面的连接还持续,然后越积越多,然后就达到mysql的最大连接数据限制了,然后新的连接就直接被拒,得到连接数过多的消息。

因为mysql配置文件使用的之前的配置文件,当时跟web同服务器,所以不存在这个问题。

这也正好解释了为什么phpMyAdmin里看mysqld状态时,有很多失败的连接,它们应该就是因反解析失败而被拒的。

 

Microsoft SQL server性能优化必备工具

这里说的工具并不一定是独立软件

1 查看sql语句执行花费的时间、IO开销

在mssql客户端执行sql语句时,先在当前会话里执行下面语句

SET STATISTICS IO ON
SET STATISTICS TIME ON
也可一次性执行
set statistics io,time on

然后再执行sql语句,运行完成的消息框里将给出如下统计信息

SQL Server 分析和编译时间: 
   CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
SQL Server 分析和编译时间: 
   CPU 时间 = 0 毫秒,占用时间 = 4 毫秒。

(100 行受影响)
表 'your_table'。扫描计数 2,逻辑读取 165 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

http://msdn.microsoft.com/zh-cn/library/ms190356.aspx

一次linux下mysql服务优化(环境为vps上的centos5)

一台vps服务器,使用centos 5操作操作系统,销售商声称是“上海戴尔VM/HV(IP)512M内存20G硬盘”,基于xen虚拟化技术,算是比中低端的vps了,上面跑一个ecshop的商城系统。

主要运行的服务为

apache (httpd-2.2.3-53.el5.centos.3/php-5.1.6-27.el5_7.5)

mysqld (mysql-server-5.0.95-1.el5_7.1)

ecshop商城上线后,访问量还并不很大,但web经常卡死,几乎访问不动。ssh登录服务器后,内存用尽,连swap都使用过半。top显示有几十个httpd进程;mysql占用cpu持续超过50%,经常达80%甚至100%, 这个状况,不死就怪了。

起初以为是apache子进程太多了,修改apache配置,只开8个子进程;同时还注意到有个yum 进程在运行,于是停掉apache,mysql,运行yum update ,升级一下系统。当时是周五下午,搞好后看起来比较正常了,

然而到了周一,问题依旧,apache进程数多达100多个!

网上有人说apache进程数过多,很可能不是apache的问题,而是web应用的问题,导致一些子进程假死或死掉。通过phpmyadmin查看mysql的进程,很多类似如下的语句:

SELECT a.attr_name
FROM `ecs_attribute` AS a, `ecs_goods_attr` AS ga, `ecs_goods` AS g
WHERE (
g.cat_id
IN ('105', '171', '173', '106', '111', '108', '113', '151', '112', '157', '153', '152', '110', '150', '147', '155', '148', '156', '172', '109', '149', '114')
OR g.goods_id
IN ('')
)
AND a.attr_id = ga.attr_id
AND g.goods_id = ga.goods_id
AND g.is_delete =0
AND g.is_on_sale =1
AND g.is_alone_sale =1
AND a.attr_id = '219'

而且查询执行时间多数比较长,经常出现多个耗时达5秒以上的语句在执行。状态经常是 Copying to tmp table,或sending data. 怀疑mysql问题比较大,开始关注mysql配置,通过phpmyadmin查看mysql变量,与一台运行平稳的实体服务器比对,主要看是缓存、临时表等变量。果然,这些值都相当的小。

查看mysql配置文件如下:

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Default to using old password format for compatibility with mysql 3.x
# clients (those using the mysqlclient10 compatibility package).
old_passwords=1

# Disabling symbolic-links is recommended to prevent assorted security risks;
# to do so, uncomment this line:
# symbolic-links=0

[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

参看windows版mysql官方自带的配置文件(\MySQL\MySQL Server 5.0\my-large.ini),修改配置文件如下:

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql

myisam_sort_buffer_size=64M
key_buffer = 64M
table_cache = 128
read_buffer_size = 1M
read_rnd_buffer_size = 1M
sort_buffer_size = 2M
myisam_sort_buffer_size = 64M
thread_cache_size = 8
query_cache_size= 16M

# Default to using old password format for compatibility with mysql 3.x
# clients (those using the mysqlclient10 compatibility package).
old_passwords=1

# Disabling symbolic-links is recommended to prevent assorted security risks;
# to do so, uncomment this line:
# symbolic-links=0

[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

重启mysql,apache,再通过phpmyadmin看查询进程,比之前大为改观。通过几个小时的观查,已经较少出现查询耗时超过5秒的进程。基本上每2、3秒重新一下一下phpmyadmin的“进程”,有一半以上机会看不到正在执行的语句。也就是说,大多数语句都可以很快执行完,以致于较很少有机会看到它们。这个现象与那台参考的实体服务器上的mysql相同。

通过free查看内存使用情况:

[root@localhost ~]# free -m
             total       used       free     shared    buffers     cached
Mem:           503        469         33          0         25        305
-/+ buffers/cache:        138        364
Swap:         1023         23       1000

swap几乎没有使用,物理内存(除去缓存)占用并也不高。

通过top查看进程:

top - 13:19:21 up 165 days,  3:11,  2 users,  load average: 0.47, 0.36, 0.52
Tasks: 101 total,   1 running,  98 sleeping,   2 stopped,   0 zombie
Cpu(s): 20.3%us, 12.5%sy,  0.0%ni, 62.1%id,  0.0%wa,  1.0%hi,  4.1%si,  0.0%st
Mem:    515268k total,   504416k used,    10852k free,    26712k buffers
Swap:  1048568k total,    23712k used,  1024856k free,   314496k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 6848 mysql     23   0  225m  56m 4432 S 32.1 11.3  33:48.61 mysqld
 7399 apache    15   0 33516  13m 4384 S  0.0  2.7   0:09.48 httpd
 7401 apache    15   0 33328  13m 3884 S  2.6  2.6   0:08.00 httpd
 7406 apache    15   0 32864  12m 3848 S  0.0  2.5   0:07.92 httpd
 7429 apache    15   0 32704  12m 3528 S  0.0  2.4   0:00.57 httpd
 7400 apache    15   0 32672  12m 3740 S  5.6  2.4   0:09.77 httpd
 7428 apache    15   0 32684  12m 3544 S  0.0  2.4   0:01.34 httpd
 7404 apache    15   0 32348  12m 3736 S  0.0  2.4   0:08.98 httpd
 7407 apache    15   0 32100  12m 3884 S  0.0  2.4   0:08.02 httpd
 7411 apache    15   0 32436  12m 3848 S  0.0  2.4   0:06.43 httpd
 7405 apache    15   0 32184  11m 3740 S  0.0  2.4   0:09.60 httpd
 7408 apache    15   0 32432  11m 3588 S  0.0  2.4   0:07.21 httpd
 7427 apache    15   0 32368  11m 3540 S  0.0  2.4   0:00.98 httpd
 6874 root      18   0 27512 9448 5672 S  0.0  1.8   0:00.40 httpd
 1765 root      34  19 27884 3200 1148 S  0.0  0.6   9:33.82 yum-updatesd
 7112 root      18   0 10216 2980 2372 S  0.0  0.6   0:00.20 sshd
 7024 root      15   0  7620 2664 1952 T  0.0  0.5   0:00.10 vim
 7114 root      15   0  6656 1608 1188 S  0.0  0.3   0:00.05 sftp-server
12180 root      15   0 25424 1188  804 S  0.0  0.2   0:34.97 snmpd
 5411 root      15   0  8520 1124 1120 T  0.0  0.2   0:00.01 mysql
 5085 root      15   0  2688 1028  800 S  0.0  0.2   0:00.20 bash
 6801 root      22   0  2504 1000  856 S  0.0  0.2   0:00.00 mysqld_safe
 7432 root      18   0  2292 1000  792 R  0.3  0.2   0:00.24 top
 1429 dbus      15   0  2964  792  544 S  0.0  0.2   2:55.54 dbus-daemon
 5077 root      15   0 10220  792  668 S  0.3  0.2   0:04.47 sshd
12307 root      15   0  9348  576  408 S  0.0  0.1   0:05.80 sendmail
12197 root      20   0 13564  572  412 S  0.0  0.1   0:04.28 snmptrapd
...

mysql的内存占用也不高,httpd进程数目也正常。

也就是说,改后的配置参数,整个vps服务器运行状态还是比较正常。

只是因为vps本身性能并不高,而访问量较多时候load average值达5以上;不过即便这时,网站还能访问;之前假死时,页面超过半分钟都打不开的。

php程序优化的几个关键点

1、如果能将类的方法定义成static,就尽量定义成static,它的速度会提升将近4倍。

2、$row[’id’] 的速度是$row[id]的7倍。

3、echo 比 print 快,并且使用echo的多重参数(译注:指用逗号而不是句点)代替字符串连接,比如echo $str1,$str2。

4、在执行for循环之前确定最大循环数,不要每循环一次都计算最大值,最好运用foreach代替。

5、注销那些不用的变量尤其是大数组,以便释放内存。

6、尽量避免使用__get,__set,__autoload。

7、require_once()代价昂贵。

8、include文件时尽量使用绝对路径,因为它避免了PHP去include_path里查找文件的速度,解析操作系统路径所需的时间会更少。

9、如果你想知道脚本开始执行(译注:即服务器端收到客户端请求)的时刻,使用$_SERVER[‘REQUEST_TIME’]要好于time()。

10、函数代替正则表达式完成相同功能。

11、str_replace函数比preg_replace函数快,但strtr函数的效率是str_replace函数的四倍。

12、如果一个字符串替换函数,可接受数组或字符作为参数,并且参数长度不太长,那么可以考虑额外写一段替换代码,使得每次传递参数是一个字符,而不是只写一行代码接受数组作为查询和替换的参数。

13、使用选择分支语句(译注:即switch case)好于使用多个if,else if语句。

14、用@屏蔽错误消息的做法非常低效,极其低效。

15、打开apache的mod_deflate模块,可以提高网页的浏览速度。

16、数据库连接当使用完毕时应关掉,不要用长连接。

17、错误消息代价昂贵。

18、在方法中递增局部变量,速度是最快的。几乎与在函数中调用局部变量的速度相当。

19、递增一个全局变量要比递增一个局部变量慢2倍。

20、递增一个对象属性(如:$this->prop++)要比递增一个局部变量慢3倍。

21、递增一个未预定义的局部变量要比递增一个预定义的局部变量慢9至10倍。

22、仅定义一个局部变量而没在函数中调用它,同样会减慢速度(其程度相当于递增一个局部变量)。PHP大概会检查看是否存在全局变量。

23、方法调用看来与类中定义的方法的数量无关,因为我(在测试方法之前和之后都)添加了10个方法,但性能上没有变化。

24、派生类中的方法运行起来要快于在基类中定义的同样的方法。

25、调用带有一个参数的空函数,其花费的时间相当于执行7至8次的局部变量递增操作。类似的方法调用所花费的时间接近于15次的局部变量递增操作。

26、Apache解析一个PHP脚本的时间要比解析一个静态HTML页面慢2至10倍。尽量多用静态HTML页面,少用脚本。

27、除非脚本可以缓存,否则每次调用时都会重新编译一次。引入一套PHP缓存机制通常可以提升25%至100%的性能,以免除编译开销。

28、尽量做缓存,可使用memcached。memcached是一款高性能的内存对象缓存系统,可用来加速动态Web应用程序,减轻数据库负载。对运算码 (OP code)的缓存很有用,使得脚本不必为每个请求做重新编译。

29、当操作字符串并需要检验其长度是否满足某种要求时,你想当然地会使用strlen()函数。此函数执行起来相当快,因为它不做任何计算,只返 回在zval 结构(C的内置数据结构,用于存储PHP变量)中存储的已知字符串长度。但是,由于strlen()是函数,多多少少会有些慢,因为函数调用会经过诸多步 骤,如字母小写化(译注:指函数名小写化,PHP不区分函数名大小写)、哈希查找,会跟随被调用的函数一起执行。在某些情况下,你可以使用isset() 技巧加速执行你的代码。
(举例如下)

if (strlen($foo) < 5) { echo “Foo is too short”$$ }

(与下面的技巧做比较)

if (!isset($foo{5})) { echo “Foo is too short”$$ }

调用isset()恰巧比strlen()快,因为与后者不同的是,isset()作为一种语言结构,意味着它的执行不需要函数查找和字母小写化。也就是说,实际上在检验字符串长度的顶层代码中你没有花太多开销。

34、当执行变量$i的递增或递减时,$i++会比++$i慢一些。这种差异是PHP特有的,并不适用于其他语言,所以请不要修改你的C或Java 代码并指望它们能立即变快,没用的。++$i更快是因为它只需要3条指令(opcodes),$i++则需要4条指令。后置递增实际上会产生一个临时变 量,这个临时变量随后被递增。而前置递增直接在原值上递增。这是最优化处理的一种,正如Zend的PHP优化器所作的那样。牢记这个优化处理不失为一个好 主意,因为并不是所有的指令优化器都会做同样的优化处理,并且存在大量没有装配指令优化器的互联网服务提供商(ISPs)和服务器。

35、并不是事必面向对象(OOP),面向对象往往开销很大,每个方法和对象调用都会消耗很多内存。

36、并非要用类实现所有的数据结构,数组也很有用。

37、不要把方法细分得过多,仔细想想你真正打算重用的是哪些代码?

38、当你需要时,你总能把代码分解成方法。

39、尽量采用大量的PHP内置函数。

40、如果在代码中存在大量耗时的函数,你可以考虑用C扩展的方式实现它们。

41、评估检验(profile)你的代码。检验器会告诉你,代码的哪些部分消耗了多少时间。Xdebug调试器包含了检验程序,评估检验总体上可以显示出代码的瓶颈。

42、mod_zip可作为Apache模块,用来即时压缩你的数据,并可让数据传输量降低80%。

43、在可以用file_get_contents替代file、fopen、feof、fgets等系列方法的情况下,尽量用 file_get_contents,因为他的效率高得多!但是要注意file_get_contents在打开一个URL文件时候的PHP版本问题;

44、尽量的少进行文件操作,虽然PHP的文件操作效率也不低的;

45、优化Select SQL语句,在可能的情况下尽量少的进行Insert、Update操作(在update上,我被恶批过);
46、尽可能的使用PHP内部函数(但是我却为了找个PHP里面不存在的函数,浪费了本可以写出一个自定义函数的时间,经验问题啊!);

47、循环内部不要声明变量,尤其是大变量:对象(这好像不只是PHP里面要注意的问题吧?);

48、多维数组尽量不要循环嵌套赋值;

49、在可以用PHP内部字符串操作函数的情况下,不要用正则表达式;

50、foreach效率更高,尽量用foreach代替while和for循环;

51、用单引号替代双引号引用字符串;

52、“用i+=1代替i=i+1。符合c/c++的习惯,效率还高”;

53、对global变量,应该用完就unset()掉;

from http://www.helion.name/?post=7