都是trigger惹的祸

这几天遇到的一个case,简单记录下。

最近应用团队的zabbix系统(由于总总原因我们大数据部门使用自己的监控系统)出现了比较严重的性能问题,zabbix db服务器一直高负载,IO接近饱和(16 SAS raid5),从监控的数据来看,每秒的读次数高达2k/s,io util一直都是100%的。


wKioL1MIxMOAqf3sAAjvboX5X_Y115.jpg


实际是只监控了1012台服务器,103113个item,1k多的nvps,由于应用运维团队对zabbix不是特别熟悉,大家武断地认为zabbix的性能已经到达瓶颈了。但是根据之前的经验,这个数据其实远远没有到达zabbix的性能瓶颈,问过之前pptv的同事,他们的zabbix集群监控了5400多台机器,100多w的item,nvps在3200左右,db的io util也不过30%左右。


wKioL1MIxNjzZXW-AAOT9AJ8h30551.jpg

为了不影响监控加上公司比较财大气粗,就直接在db server上使用flash卡了。。但是加上flash卡之后,db的性能并没有变好转,io压力还是很高。


wKiom1MIxQ-hzuWzAAMh8gLaupM395.jpg


看来问题没有这么简单。于是和同事开始查找原因:

在db上开启general log来抓取实时的select信息,在zabbix item更新的时候会有如下操作:


wKiom1MIxSHS19R3AAbWSjVQoXY858.jpg

首先取出item的相关信息,然后通过update语句来更新这个item的信息,因为所有的select都在一个事务里,这样用了mysql-proxy也无读写分离。

另外发现不少的item更新会有 select x  from history_uint where itemid=xxx and clock<= now();的查询,通过explain 查看,虽然对history的相关表都做了分区,但是这条语句仍然扫描了大多数分区的数据,这就造成响应缓慢,同时因为需要扫描大量的partition,又会需要大量的io操作。


zabbix 04:25:55>explain partitions select value from history_uint where itemid=41597 and clock<=1390720637\G
          id: 1
 select_type: SIMPLE
       table: history_uint
  partitions: p20140112,p20140113,p20140114,p20140115,p20140116,p20140117,p20140118,p20140119,p20140120,p20140121,p20140122,p20140123,p20140124,p20140125,p20140126
        type: range
possible_keys: history_uint_1
         key: history_uint_1
  key_len: 12
         ref: NULL
        rows: 9687
       Extra: Using where
1 row in set (0.00 sec)


这个sql是由trigger触发的,在item每次更新操作完成后,都会通过这个sql查询trigger中设置的判断值。通过查询items表和hosts表找到这个item的trigger相关设置,发现语法中有last(#0)的情况:


wKiom1MIxXfy13pwAACzOF82gBY426.jpg

在trigger语法中,last(#x)表示最后几个,zabbix通过trigger的语法来拼出select的sql,但是这个版本的zabbix有bug,在解析这种trigger语法的时候会出问题,最后产生了没有查询范围的sql.
bugid: https://support.zabbix.com/browse/ZBX-6476

原因找到了,直接通过update functions表把#0的都变成0就可以了。
update functions set parameter='0' where parameter='#0';

小结:许多zabbix的性能问题可以由分析zabbix的db的general log和slow log来解决。在设置trigger时,需要设置一个有效地时间范围。

你可能感兴趣的:(性能,trigger,zabbix)