[Mysql]备份同库中一张表的历史记录 insert into ..select

需求

如今有个这么一个需求。mysql中有个表。数据增长的非常快。可是呢这个数据有效期也就是1个月,一个月曾经的记录不太重要了,可是又不能删除。为了保证这个表的查询速度,须要一个简单的备份表,把数据倒进去。

代码

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

原始表radius 备份的表为 radius2015

#!/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=‘%(asctime)s %(levelname)s -     %(message)s‘)
logger = logging.getLogger(‘backup‘)
logger.setLevel(logging.DEBUG)

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

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

create_table_sql = ‘‘‘
CREATE TABLE `{0}` (
  `radacctid` bigint(21) NOT NULL AUTO_INCREMENT,
  `acctsessionid` varchar(64) NOT NULL DEFAULT ‘‘,
  `acctuniqueid` varchar(32) NOT NULL DEFAULT ‘‘,
  `username` varchar(64) NOT NULL DEFAULT ‘‘,
  `groupname` varchar(64) NOT NULL DEFAULT ‘‘,
  `realm` varchar(64) DEFAULT ‘‘,
  `nasipaddress` varchar(15) NOT NULL DEFAULT ‘‘,
  `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 ‘‘,
  `callingstationid` varchar(50) NOT NULL DEFAULT ‘‘,
  `acctterminatecause` varchar(32) NOT NULL DEFAULT ‘‘,
  `servicetype` varchar(32) DEFAULT NULL,
  `framedprotocol` varchar(32) DEFAULT NULL,
  `framedipaddress` varchar(15) NOT NULL DEFAULT ‘‘,
  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
‘‘‘

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

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

#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 = {
        ‘default‘: {
            ‘host‘: "",
            ‘user‘: "",
            ‘database‘: "",
            ‘password‘: "",
            ‘charset‘: "",
        }
    }

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

    def __enter__(self):
        try:
            self.conn = MySQLdb.connect(
                user=self.connconfig[‘user‘],
                db=self.connconfig[‘database‘],
                passwd=self.connconfig[‘password‘],
                host=self.connconfig[‘host‘],
                use_unicode=True,
                charset=self.connconfig[‘charset‘] 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 ‘%s: %s‘ % (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 ‘{0}‘".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")

本文出自 “orangleliu笔记本” 博客,转载请务必保留此出处http://blog.csdn.net/orangleliu/article/details/46650875 作者orangleliu 採用署名-非商业性使用-同样方式共享协议

时间: 07-08

[Mysql]备份同库中一张表的历史记录 insert into ..select的相关文章

查看Sql Server库中某张表的结构

--快速查看表结构(比较全面的) SELECT CASE WHEN col.colorder = 1 THEN obj.name ELSE '' END AS 表名, col.colorder AS 序号 , col.name AS 列名 , ISNULL(ep.[value], '') AS 列说明 , t.name AS 数据类型 , col.length AS 长度 , ISNULL(COLUMNPROPERTY(col.id, col.name, 'Scale'), 0) AS 小数位数

从MySQL全库备份中恢复某个库和某张表【转】

从MySQL全库备份中恢复某个库和某张表 一.全库备份-A [[email protected] backup]#mysqldump -uroot -p123456 --default-character-set=utf8 --single-transaction --extended-insert=false --hex-blob --master-data=2 --log-error=/tmp/test.err --routines --triggers --events --quick -

利用mysql和mysqli取得mysql的所有数据库和库中的所有表

功能:利用mysql和mysqli两种连接数据库的方法,取得Mysql服务器上的所有数据库和库中的所有表. 环境:自己用分开安装apache mysql php搭建的环境 操作系统是:windows 10 代码如下: <?php/** * mysqli  op mysql demo *//** * 公用函数 */ /** * 功能:列出一个数据库的所有表 * @param $dbname * @param $con */function list_tables($dbname,$con)    

mysql 如何将一个库的一个表的数据复制到另一个库中的一个表

insert   库2..表2   select   字段1,字段2   from   库1..表1 where 条件 https://www.cnblogs.com/banruo/archive/2010/09/07/1820285.html 如果 库 中没有这个表 Create table Table2 (Select * from Table1); https://blog.csdn.net/wangluo605/article/details/82289209 原文地址:https://

查找当前数据库服务器中某张表存在于哪个数据库中

1 -- 2 --查找当前数据库服务器中某张表存在于哪个数据库中,sqlserver2008测试通过 3 -- 4 declare @tableName varchar(50) 5 --这里设置要查询的表名字 6 set @tableName='Products' 7 8 --清理临时表 9 if object_id('tempdb..#tmpdbs') is not null Begin 10 drop table #tmpdbs 11 End 12 if object_id('tempdb.

sql 从一个库中取某个表的数据导入到另一个库中相同结构的表中

sql 2008 从一个库中把 某个表中的数据导入到另一个库中的具有相同结构的表中 use 库1 go insert into  库1.dbo.表1  select * from  库2.dbo.表1 在这里会遇到一个问题:如果此表的主键或者其中有一个列使用了 IDENTITY(1,1) 自增长时,但又想手动为此列指定时 会出现一个错误.我的做法是先把插入表1的自增给取消,插入成功后在给改过来.

mysql 从相同类型的多张表中提取到一张表中

蜗牛背着沉重的壳,贴着地面一步步艰难地向前爬行,不回头,也不左顾右盼,只是朝着自己想到达的地方行进. 有时候需要从多张相同类型的表中提取数据,这些表有一些相同的列或者表结构完全相同,同时表名存在一定的规律,如果表数量少还好,如果表数量多的话则会比较繁琐.可以通过存储过程将多张表的数据提取到一张表的方法来降低工作量. 先创建测试表并生成测试数据.以下存储过程创建10张测试表,每张表生成10条测试数据.drop PROCEDURE if EXISTS create10tables;create PR

数据库中两张表之间的数据同步实现思路(增加、删除、更新)Mysql、sqlserver

分别创建增加.删除.更新的触发器(Trigger)来达到两张表之间数据同步的目的. 1:数据同步增加:如有两张表--A表和B表,创建触发器使当A表插入数据后B表也同步插入数据.其中B表插入数据的字段需要同A表中的字段相对应. CREATE TRIGGER 触发器名称 ON A表 AFTER INSERT AS BEGIN INSERT INTO B表(B表字段1,B表字段2,B表字段3) SELECT A表字段1,A表字段2,A表字段3 FROM INSERTED END 2.数据同步删除:如有

快速恢复slave从库的几张表

由于数据库很大,只恢复几张表既可以使用.恢复方法如下: 停止slave复制,stop slave; 在主库上导出这三张表,并记录binlog和pos点: mysqldump --single-transaction--master_data=2 dbname table1 table2 table3>dbname_table(123).sql 查看导出的sql脚本,在脚本头部有binlog和pos点. 查看导出的sql脚本负载到从库上,并change master to : start slav