zabbix环境mysql分区表管理历史数据_python实现
zabbix添加数据库表partition
zabbix系统自身有housekeeper进程来清除超过保留时间的数据,但是数据量上来之后就会比较影响性能,因此可以使用mysql的表分区来解决这个问题,这里将管理表分区写成一个可执行的python文件,这样只需设置定时任务去处理就好了。当设置表分区来管理历史数据和趋势数据后就可以在zabbix配置页面关掉histoty和trend数据管理。
具体代码
# -*- coding: utf-8 -*-
import os
import platform
import datetime
import time
import signal
from subprocess import PIPE, Popen
MYSQL_BIN = "/usr/bin/mysql"
MYSQL_USER = "zabbix"
MYSQL_PWD = "zabbix"
MYSQL_DB = "zabbix"
MYSQL_PORT = "3306"
MYSQL_HOST = "127.0.0.1"
# 历史数据保留时间,单位天
HISTORY_DAYS = 30
# 趋势数据保留时间,单位月
TREND_MONTHS = 12
class Mysql(object):
HISTORY_TABLE = "history, history_log, history_str, history_text, history_uint"
TREND_TABLE = "trends, trends_uint"
PARTITION_SELECT = """SELECT PARTITION_NAME FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME = '{table}';"""
CREATE_PARTITION = """ALTER TABLE {table} PARTITION BY RANGE( clock ) (PARTITION p{partition_date} VALUES LESS THAN ({time_s}));"""
ADD_PARTITION = """ALTER TABLE {table} ADD PARTITION (PARTITION p{partition_date} VALUES LESS THAN ({time_s}));"""
DEL_PARTITION = """ALTER TABLE {table} DROP PARTITION {partition};"""
def __init__(self, host=MYSQL_HOST, username=MYSQL_USER,
password=MYSQL_PWD, port=MYSQL_PORT, db=MYSQL_DB):
self._host = host
self._username = username
self._password = password
self._port = port
self._db = db
self._mysql_prefix_cmd = self._init_pre_cmd()
def _init_pre_cmd(self):
base_cmd = "{mysql_bin} -u{user} -p{pwd} -h{host} -P{port} {db} -e"
return base_cmd.format(mysql_bin=MYSQL_BIN, user=self._username,
pwd=self._password, host=self._host, port=self._port, db=self._db)
def run_cmd(self, cmdstr):
sql_cmd = '{0} "{1}"'.format(self._mysql_prefix_cmd, cmdstr)
cmd_ut = Cmds(sql_cmd, timeout=2)
stdo = cmd_ut.stdo()
stde = cmd_ut.stde()
retcode = cmd_ut.code()
if retcode != 0:
raise Exception('run cmd error: {}'.format(stde))
else:
return stdo
def _hand_partition_res(self, p_res, drop_pre_stand):
"""
:param p_res: select table partition return info
:param drop_pre_stand: drop data according to the date num
:return: will drop partition name list
"""
pars_li = filter(lambda x: x[1:].isdigit(), p_res.split())
res = filter(lambda x: int(x[1:]) <= drop_pre_stand, pars_li)
return list(res)
def create_partitions_history(self):
for table in self.HISTORY_TABLE.split(","):
table = table.strip()
print(table)
query_parti = self.PARTITION_SELECT.format(table=table)
p_res = self.run_cmd(query_parti)
p_li = list(filter(lambda x: x[1:].isdigit(), p_res.split()))
if not p_li:
td = str(datetime.datetime.today().date())
td = ''.join(td.split("-"))
timest = int(
time.mktime(
time.strptime(
"{} 23:59:59".format(td),
"%Y%m%d %H:%M:%S")))
try:
sql_cmd = self.CREATE_PARTITION.format(
table=table, partition_date=td, time_s=timest)
# print(sql_cmd)
self.run_cmd(sql_cmd)
print(
"table {0} create partition {1} succeed".format(
table, "p" + td))
except Exception as e:
print(
"table {0} create partition {1} failed".format(
table, "p" + td))
print(e)
continue
after_days = list(map(lambda x: ''.join(
x.split("-")), Util.get_after_days(7)))
for d in after_days:
if "p{}".format(d) not in p_li:
time_s = int(
time.mktime(
time.strptime(
"{} 23:59:59".format(d),
"%Y%m%d %H:%M:%S")))
try:
self.run_cmd(
self.ADD_PARTITION.format(
table=table,
partition_date=d,
time_s=time_s))
print(
"table {0} create partition {1} succeed".format(
table, "p" + d))
except Exception as e:
print(
"table {0} create partition {1} failed".format(
table, "p" + d))
print(e)
continue
def create_partitions_trend(self):
for table in self.TREND_TABLE.split(","):
table = table.strip()
print(table)
query_parti = self.PARTITION_SELECT.format(table=table)
p_res = self.run_cmd(query_parti)
p_li = list(filter(lambda x: x[1:].isdigit(), p_res.split()))
if not p_li:
tm = time.strftime("%Y%m", time.localtime())
tm_time = tm + "01 00:00:00"
timest = int(
time.mktime(
time.strptime(
tm_time,
"%Y%m%d %H:%M:%S")))
try:
sql_cmd = self.CREATE_PARTITION.format(
table=table, partition_date=tm, time_s=timest)
self.run_cmd(sql_cmd)
print(
"table {0} create partition {1} succeed".format(
table, "p" + tm))
except Exception as e:
print(
"table {0} create partition {1} failed".format(
table, "p" + tm))
print(e)
continue
after_months = Util.get_after_months(5)
for d in after_months:
if "p{}".format(d) not in p_li:
time_s = int(
time.mktime(
time.strptime(
d + "01 00:00:00",
"%Y%m%d %H:%M:%S")))
try:
self.run_cmd(
self.ADD_PARTITION.format(
table=table,
partition_date=d,
time_s=time_s))
print(
"table {0} create partition {1} succeed".format(
table, "p" + d))
except Exception as e:
print(
"table {0} create partition {1} failed".format(
table, "p" + d))
print(e)
continue
def drop_partitions_history(self):
for table in self.HISTORY_TABLE.split(","):
table = table.strip()
query_parti = self.PARTITION_SELECT.format(table=table)
p_res = self.run_cmd(query_parti)
pre_day = ''.join(Util.get_pre_day(HISTORY_DAYS).split("-"))
will_del_pars = self._hand_partition_res(p_res, pre_day)
for par in will_del_pars:
self.run_cmd(
self.DEL_PARTITION.format(
table=table, partition=par))
def drop_partitions_trend(self):
for table in self.TREND_TABLE.split(","):
table = table.strip()
query_parti = self.PARTITION_SELECT.format(table=table)
p_res = self.run_cmd(query_parti)
pre_month = Util.get_pre_month(TREND_MONTHS)
will_del_pars = self._hand_partition_res(p_res, pre_month)
for par in will_del_pars:
self.run_cmd(
self.DEL_PARTITION.format(
table=table, partition=par))
class Cmds(object):
def __init__(self, *args, **kwargs):
self.ps = None
self.stdout = None
self.stderr = None
self.retcode = 0
self.cmds(*args, **kwargs)
def cmds(self, command, env=None, stdout=PIPE, stderr=PIPE, timeout=None):
if platform.system() == "Linux":
self.ps = Popen(
command,
stdout=stdout,
stdin=PIPE,
stderr=stderr,
shell=True)
else:
self.ps = Popen(
command,
stdout=stdout,
stdin=PIPE,
stderr=stdout,
shell=False)
if timeout:
start = datetime.datetime.now()
while self.ps.poll() is None:
time.sleep(0.2)
now = datetime.datetime.now()
if (now - start).seconds > timeout:
os.kill(self.ps.pid, signal.SIGINT)
self.retcode = -1
self.stdout = None
self.stderr = None
return self
kwargs = {'input': self.stdout}
(self.stdout, self.stderr) = self.ps.communicate(**kwargs)
self.retcode = self.ps.returncode
return self
def __repr__(self):
return self.stdo()
def __unicode__(self):
return self.stdo()
def __str__(self):
try:
import simplejson as json
except BaseException:
import json
res = {
"stdout": self.stdout,
"stderr": self.stderr,
"retcode": self.retcode}
return json.dumps(res, separators=(',', ':'),
ensure_ascii=False).encode('utf-8')
def stdo(self):
if self.stdout:
return self.stdout.strip().decode('utf-8')
return ''
def stde(self):
if self.stderr:
return self.stderr.strip().decode('utf-8')
return ''
def code(self):
return self.retcode
class Util(object):
@staticmethod
def get_pre_days(days):
end = datetime.datetime.today().date()
day_all = [str(end)]
while days:
end -= datetime.timedelta(days=1)
day_all.append(str(end))
days -= 1
return day_all[::-1]
@staticmethod
def get_pre_day(days):
return str(datetime.datetime.today().date() -
datetime.timedelta(days=days))
@staticmethod
def get_after_days(days):
start = datetime.datetime.today().date()
day_all = [str(start)]
while days:
start += datetime.timedelta(days=1)
day_all.append(str(start))
days -= 1
return day_all
@staticmethod
def get_pre_months(months):
end = int(time.strftime("%Y%m", time.localtime()))
month_all = [str(end)]
while months:
if str(end).endswith("01"):
end -= 89
else:
end -= 1
month_all.append(str(end))
months -= 1
return month_all[::-1]
@staticmethod
def get_pre_month(months):
end = int(time.strftime("%Y%m", time.localtime()))
while months:
if str(end).endswith("01"):
end -= 89
else:
end -= 1
months -= 1
return str(end)
@staticmethod
def get_after_months(months):
start = int(time.strftime("%Y%m", time.localtime()))
month_all = [str(start)]
while months:
if str(start).endswith("12"):
start += 89
else:
start += 1
month_all.append(str(start))
months -= 1
return month_all
def main():
mysql = Mysql(
host=MYSQL_HOST,
username=MYSQL_USER,
password=MYSQL_PWD,
port=MYSQL_PORT,
db=MYSQL_DB)
mysql.create_partitions_history()
mysql.create_partitions_trend()
mysql.drop_partitions_history()
mysql.drop_partitions_trend()
if __name__ == '__main__':
main()
zabbix环境mysql分区表管理历史数据_python实现的更多相关文章
- MySQL分区表管理
RANGE,LIST分区管理 1:为未分区表创建分区 ALTER TABLE trb3 PARTITION BY KEY(id) PARTITIONS 2; 2:删除某个分区的数据 ALTER TAB ...
- Mysql --分区表的管理与维护
改变一个表的分区方案只需使用alter table 加 partition_options 子句就可以了.和创建分区表时的create table语句很像 创建表 CREATE TABLE trb3 ...
- 数据切分——Mysql分区表的管理与维护
关于Mysql分区表的介绍可以参考: http://blog.csdn.net/jhq0113/article/details/44592865 关于Mysql分区表的创建可以参考: http://b ...
- zabbix监控mysql性能
使用zabbix监控mysql的三种方式 1.只是安装agent 2.启用模板监控 3.启用自定义脚本的模板监控 zabbix中默认有mysql的监控模板.默认已经在zabbix2.2及以上的版本中. ...
- MySQL 分区表原理及数据备份转移实战
MySQL 分区表原理及数据备份转移实战 1.分区表含义 分区表定义指根据可以设置为任意大小的规则,跨文件系统分配单个表的多个部分.实际上,表的不同部分在不同的位置被存储为单独的表.用户所选择的.实现 ...
- 生产环境MySQL数据库集群MHA上线实施方案
生产环境MySQL数据库集群MHA上线实施方案 一.不停库操作 1.在所有节点安装MHAnode所需的perl模块(需要有安装epel源) yum install perl-DBD-MySQL -y ...
- zabbix实现mysql数据库的监控(四)
前面介绍的内容都是用第三方开发好的插件进行mysql监控的,可能有些我们关心的监控内容并不在其中,这时一种常用的方法就是定义我们自己的脚本并将它整合到zabbix中,从而在原有监控的基础上进行有力的补 ...
- zabbix监控MySQL,Tomcat及配置邮件报警
目录 一.思路 二.部署.配置 环境 安装zabbix 对zabbix进行初步优化 添加监控主机 部署监控Tomcat 配置邮件报警 三.总结 一.思路 首先搭建zabbixserver,本机需要安装 ...
- MySQL 分区表,为什么分区键必须是主键的一部分?
随着业务的不断发展,数据库中的数据会越来越多,相应地,单表的数据量也会越到越大,大到一个临界值,单表的查询性能就会下降. 这个临界值,并不能一概而论,它与硬件能力.具体业务有关. 虽然在很多 MySQ ...
随机推荐
- distinct 排除重复 函数
select count(distinct uid) from ib_user_settings; 参考: http://www.w3school.com.cn/sql/sql_distinct.as ...
- mysql删除一条记录
mysql如何删除一条记录 delete from 表名 where 条件 实例: use db1 delete from tb1 where id = 1;
- Ubuntu 18.04 下 PostgreSQL 10 的安装与基础配置
下载安装 在命令行执行如下语句: apt-get install postgresql-10 该指令会帮助你下载如下PostgreSQL组件: name |explain | ------------ ...
- nginx 配置 https 并强制跳转(lnmp一键安装包)
目录 一.安装包 二.配置 三.查看配置文件 3.1.设定强制跳转 https 3.2 Rewrite 常用全局变量举例 一.安装包 安装大家按照官方说的安装即可. ./install.sh lnmp ...
- typing-python用于类型注解的库
简介 动态语言的灵活性使其在做一些工具,脚本时非常方便,但是同时也给大型项目的开发带来了一些麻烦. 自python3.5开始,PEP484为python引入了类型注解(type hints),虽然在p ...
- C#使用CUDA
随着信息处理的爆炸增长,传统使用CPU计算已经无法满足计算作业增长的需求,GPU的出现为批量作业提供了新的契机.GPU计算拥有很类库,比如CUDA.OpenCL等,但是可以发现CUDA是其中相对比较成 ...
- sqlmap(网站数据库注入)
*教程 http://www.nxadmin.com/tools/1241.html 一.ASP网站 1. sqlmap -u “http://www.czypjx.com/News_show.asp ...
- centOS服务器-firewall防火墙开放端口
前言 日常开发中,我们常常会因为服务器各种端口未开放出现各种问题,下面我们就来简单了解下服务器上的端口开放!!! 作为一个后台开发,日常接触最多的除了代码就是服务器了: 产品:谁谁, 线上有个功能报错 ...
- UWP笔记-自定义Grid背景图片
之前写简单的UWP版本地音乐播放器,有自定义背景壁纸的功能,现在贴在这里回顾下. Page.xaml 页面,添加Grid <Grid x:Name="mainGrid"/&g ...
- MIT 6.828 课程介绍
MIT 6.828 课程介绍 本文是对MIT 6.828操作系统课程介绍的简单摘录,详细介绍见6.828: Learning by doing以及朱佳顺的推荐一门课:6.828.学习资源均可以在课程主 ...