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 ...
随机推荐
- shell练习题集合
1. 获取ip或MAC地址(方法不唯一) [root@cicd ~]# ip a| grep 'inet' | awk -F " +" '{print $3}'| awk -F & ...
- 【转载】CentOS7下使用LVM给系统硬盘扩容
原文地址:https://www.cnblogs.com/ding2016/p/9680690.html 简单介绍: LVM是逻辑盘卷管理(Logical Volume Manager)的简称,它是L ...
- Android之FrameWork
1 Activity的生命周期和启动模式 1.1 Activity的生命周期全面分析 用户正常使用情况下的生命周期 & 由于Activity被系统回收或者设备配置改变导致Activity被销毁 ...
- 学习Yii(2)
Yii拥有很好的手册,还是中文的,官方的手册很详细.还是应该好好看一下.今天就开始跟着项目代码调试. 上次看到入口脚本,学习一定要快,要用心,抓住时间.不然时间拖久了就忘了.延续不上,大打折扣.而且要 ...
- Unstanding LSTM
1.RNNs 我们可以把RNNs看成一个普通网络做多次复制后叠加在一起组合起来,每一个网络都会把输出传递到下一个网络中. 把RNNs按时间步上展开,就得到了下图: 从RNNs链状结构可以容易理解到他是 ...
- Mysql的binlog 和InnoDB的redo-log
来源:https://www.jianshu.com/p/4bcfffb27ed5 mysql日志系统之redo log和bin log Mr林_月生关注 12018.12.02 01:35:06字数 ...
- # 【ARM-Linux开发】在Win7的电脑上直接运行安装Ubuntu14.04发生的问题 标签(空格分隔): 【Linux开发】 --- > 一段时间以来,一直是在Windows上安装虚拟机
[ARM-Linux开发]在Win7的电脑上直接运行安装Ubuntu14.04发生的问题 标签(空格分隔): [Linux开发] 一段时间以来,一直是在Windows上安装虚拟机,然后安装Ubuntu ...
- Beta冲刺博客
这个作业属于哪个课程 当然是属于程序分析与设计呀 这个作业要求在哪里 在这儿 团队名称 六扇门编程小组(团队博客) 这个作业的目标 完成为期两周的β版本冲刺 1.团队信息 姓名 学号 曹欢(组长) 2 ...
- 洛谷P3381 最小费用最大流模板
https://www.luogu.org/problem/P3381 题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用 ...
- Django soft-delete软删除
在django中,实现这个功能很简单,我们采用一个字段用来保存删除的时间.若记录没有被删除,那么设置该值为None,如果被删除,那么设置时间为删除的时间. class BaseSchema(model ...