Home > Database > Mysql Tutorial > body text

[Mysql]备份同库中一张表的历史记录insertinto..select_MySQL

WBOY
Release: 2016-06-01 12:59:51
Original
1342 people have browsed it

需求

现在有个这么一个需求,mysql中有个表,数据增长的很快,但是呢这个数据有效期也就是1个月,一个月以前的记录不太重要了,但是又不能删除。为了保证这个表的查询速度,需要一个简单的备份表,把数据倒进去。

代码

于是我写了一个小脚本,用来做定时任务,把这个表某段时间的数据备份到备份表中,核心就是个简单的sql。

原始表radius 备份的表为 radius2015

<code class="hljs python">#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
#python2.7x
#authror: orangleliu
#备份radius中的上网记录表,每个月备份一次,原始表中保留一份数据
#使用同一个数据库中的一个不同表名的表备份

import time
import datetime
import logging
from datetime import timedelta

import MySQLdb
import MySQLdb.cursors


logging.basicConfig(format=&#39;%(asctime)s %(levelname)s - \
    %(message)s&#39;)
logger = logging.getLogger(&#39;backup&#39;)
logger.setLevel(logging.DEBUG)

#数据库配置
DBPARAMS = {
    "host":"127.0.0.1",
    "user":"root",
    "password":"",
    "database":"test",
    "charset": ""
}

#这里使用select into 来备份,数据校验对比记录数,一个月大概100w条数据
#radacct2015
#检查表,检查重传,备份,校验

create_table_sql = &#39;&#39;&#39;
CREATE TABLE `{0}` (
  `radacctid` bigint(21) NOT NULL AUTO_INCREMENT,
  `acctsessionid` varchar(64) NOT NULL DEFAULT &#39;&#39;,
  `acctuniqueid` varchar(32) NOT NULL DEFAULT &#39;&#39;,
  `username` varchar(64) NOT NULL DEFAULT &#39;&#39;,
  `groupname` varchar(64) NOT NULL DEFAULT &#39;&#39;,
  `realm` varchar(64) DEFAULT &#39;&#39;,
  `nasipaddress` varchar(15) NOT NULL DEFAULT &#39;&#39;,
  `nasportid` varchar(15) DEFAULT NULL,
  `nasporttype` varchar(32) DEFAULT NULL,
  `acctstarttime` int(11) DEFAULT NULL,
  `acctupdatetime` int(11) DEFAULT NULL,
  `acctstoptime` int(11) DEFAULT NULL,
  `acctinterval` int(12) DEFAULT NULL,
  `acctsessiontime` int(12) unsigned DEFAULT NULL,
  `acctauthentic` varchar(32) DEFAULT NULL,
  `connectinfo_start` varchar(50) DEFAULT NULL,
  `connectinfo_stop` varchar(50) DEFAULT NULL,
  `acctinputoctets` bigint(20) DEFAULT NULL,
  `acctoutputoctets` bigint(20) DEFAULT NULL,
  `calledstationid` varchar(50) NOT NULL DEFAULT &#39;&#39;,
  `callingstationid` varchar(50) NOT NULL DEFAULT &#39;&#39;,
  `acctterminatecause` varchar(32) NOT NULL DEFAULT &#39;&#39;,
  `servicetype` varchar(32) DEFAULT NULL,
  `framedprotocol` varchar(32) DEFAULT NULL,
  `framedipaddress` varchar(15) NOT NULL DEFAULT &#39;&#39;,
  PRIMARY KEY (`radacctid`),
  UNIQUE KEY `acctuniqueid` (`acctuniqueid`),
  KEY `username` (`username`),
  KEY `framedipaddress` (`framedipaddress`),
  KEY `acctsessionid` (`acctsessionid`),
  KEY `acctsessiontime` (`acctsessiontime`),
  KEY `acctstarttime` (`acctstarttime`),
  KEY `acctinterval` (`acctinterval`),
  KEY `acctstoptime` (`acctstoptime`),
  KEY `nasipaddress` (`nasipaddress`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
&#39;&#39;&#39;


back_sql = &#39;&#39;&#39;
INSERT INTO {0}
SELECT *
FROM {1}
WHERE acctstarttime < UNIX_TIMESTAMP(
   STR_TO_DATE(&#39;{2}&#39;, &#39;%Y-%m-%d&#39;)
) AND acctstarttime >= UNIX_TIMESTAMP(
   STR_TO_DATE(&#39;{3}&#39;, &#39;%Y-%m-%d&#39;)
)&#39;&#39;&#39;


count_sql = """
SELECT count(*) FROM {0} WHERE 1=1 AND
acctstarttime < UNIX_TIMESTAMP(
   STR_TO_DATE(&#39;{1}&#39;, &#39;%Y-%m-%d&#39;)
) AND acctstarttime >= UNIX_TIMESTAMP(
   STR_TO_DATE(&#39;{2}&#39;, &#39;%Y-%m-%d&#39;)
)
"""


#date tools
def get_year(month):
    #month like 201505
    return datetime.datetime.strptime(month, "%Y%m").year


def get_month_firstday_str(month):
    return datetime.datetime.strptime(month,"%Y%m").\
                                        strftime("%Y-%m-%d")

def get_next_month_firstday_str(month):
    month_firstday = datetime.datetime.strptime(month,"%Y%m")
    monthnum = month_firstday.month
    return "{0}-{1}-{2}".format(
            month_firstday.year if monthnum < 12 else \
                                 month_firstday.year + 1,
            monthnum + 1 if monthnum < 12 else 1, 1)


class DBConn(object):
    __CONFIG = {
        &#39;default&#39;: {
            &#39;host&#39;: "",
            &#39;user&#39;: "",
            &#39;database&#39;: "",
            &#39;password&#39;: "",
            &#39;charset&#39;: "",
        }
    }

    def __init__(self, connname=&#39;&#39;, connconfig={}):
        if connconfig:
            self.connconfig = connconfig
        else:
            connname = connname or &#39;default&#39;
            self.connconfig = self.__CONFIG.get(connname, &#39;default&#39;)
        self.conn = None

    def __enter__(self):
        try:
            self.conn = MySQLdb.connect(
                user=self.connconfig[&#39;user&#39;],
                db=self.connconfig[&#39;database&#39;],
                passwd=self.connconfig[&#39;password&#39;],
                host=self.connconfig[&#39;host&#39;],
                use_unicode=True,
                charset=self.connconfig[&#39;charset&#39;] or "utf8",
                #cursorclass=MySQLdb.cursors.DictCursor
                )

            return self.conn
        except Exception, e:
            print str(e)
            return None

    def __exit__(self, exe_type, exe_value, exe_traceback):
        if exe_type and exe_value:
            print &#39;%s: %s&#39; % (exe_type, exe_value)
        if self.conn:
            self.conn.close()


class RadiusBackup(object):
    def __init__(self, month, conn):
        self.conn = conn
        self.cursor = conn.cursor()
        self.month = month
        self.year = get_year(month)
        self.month_firstday = get_month_firstday_str(month)
        self.next_month_firstday = get_next_month_firstday_str(month)
        self.tablename = "radacct{0}".format(self.year)
        self.stable = "radacct"


    def check_table_exist(self):
        check_table_sql = "SHOW TABLES LIKE &#39;{0}&#39;".format(
                            self.tablename)
        self.cursor.execute(check_table_sql)
        res = self.cursor.fetchall()
        return True if len(res) > 0 else False


    def create_backup_table(self):
        sql = create_table_sql.format(self.tablename)
        self.cursor.execute(sql)
        logger.info(u"开始创建备份表 {0}".format(self.tablename))


    def check_datas_count(self, tablename):
        sql = count_sql.format(tablename, self.next_month_firstday,
                    self.month_firstday)
        logger.debug(sql)
        self.cursor.execute(sql)
        res = self.cursor.fetchone()
        return res[0]


    def check_before(self):
        flag = False
        #check table
        if not self.check_table_exist():
            self.create_backup_table()
            if self.check_table_exist() == False:
                logger.error(u"无法找到备份表 exit")
                return flag
        #check datas
        if self.check_datas_count(self.tablename) > 0:
            return flag
        else:
            return True


    def backup_datas(self):
        sql = back_sql.format(self.tablename, self.stable,
                self.next_month_firstday, self.month_firstday)
        logger.debug(sql)
        self.cursor.execute(sql)
        self.conn.commit()


    def check_after(self):
        snum = self.check_datas_count(self.stable)
        bnum = self.check_datas_count(self.tablename)
        if snum > 0 and (snum == bnum):
            logger.info(u"备份成功")
            return snum, True
        else:
            return -1, False

    def backup_handler(self):
        if self.check_before():
            logger.info(u"检查完毕,开始备份数据")
            self.backup_datas()
            logger.info(u"开始备份")
            num, flag = self.check_after()
            logger.info(u"本次备份{0} 数据 {1}条".format(self.month, num))
        else:
            logger.info(u"数据已经有备份,请检查")


if __name__ == "__main__":
    month = "201504"

    with DBConn(connconfig=DBPARAMS) as dbconn:
        if dbconn:
            backup = RadiusBackup(month, dbconn)
            backup.backup_handler()
        else:
            logger.error("can not connect to db")</code>
Copy after login
Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!