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 ...
随机推荐
- Freemarker使用总结
spring mvc 中 Freemarker 获取项目根目录,方便HTML页面配置各种路径 在SpringMVC框架中使用Freemarker试图时,要获取根路径的方式如下: <!-- Fre ...
- Node.js起一个web服务器
开启服务: 代码如下: var http = require('http'); http.createServer(function (request, response) { // 发送 HTTP ...
- iOS自定义下拉列表
实现效果如下: 点击导航栏的“点击”,弹出下拉列表. 注意:绿色的是控制器的view背景,又一个遮罩层,点击可以隐藏列表. Github地址: https://github.com/PengSiSi/ ...
- 【ABAP系列】SAP ABAP BAPI_REQUISITION_CREATE创建采购申请
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP BAPI_RE ...
- redis分布式锁,面试官请随便问,我都会
目录 前言 实现要点 错误解锁方式 正确加锁释放锁方式 前言 现在的业务场景越来越复杂,使用的架构也就越来越复杂,分布式.高并发已经是业务要求的常态.像腾讯系的不少服务,还有CDN优化.异地多备份等处 ...
- 在VMware上部署MOS(MirantisOpenStack-6.0)搭建全过程
安装清单 MOS9.0系统镜像 1 MirantisOpenStack-6.0.iso ****首先创建3个仅主机模式网卡, 禁用DHCP,分别配置ip为 /10.20.0.0 /172.16.0.0 ...
- ffmpeg学习笔记-Linux下编译Android动态库
Android平台要使用ffmpeg就需要编译生成动态库,这里采用Ubuntu编译Android动态库 文件准备 要编译生成Android需要以下文件 NDK ffmpeg源代码 NDK下载 NDK可 ...
- 记录下为了玩 docker 安装 CentOS 7 最简化版后遇到的一些问题
今天我的腾讯云服务器在使用docker安装ElasticSearch和Kibana的时候内存不够,安装完直接卡死.所以无奈只能在本地上跑VMWare安装CentOS7来运行测试. 从阿里云镜像地址:h ...
- [转帖].NET导出Excel的四种方法及评测
.NET导出Excel的四种方法及评测 https://www.cnblogs.com/sdflysha/p/20190824-dotnet-excel-compare.html 导出Excel是.N ...
- SQL SERVER 字符串函数 STRING_SPLIT()
定义: STRING_SPLIT()函数根据指定的分隔符将字符串拆分为子字符串行. ※STRING_SPLIT 要求兼容性级别至少为 130. (即SSMS 2016及以上版本) ※级别低于 130 ...