前言:DB2一个实例下,可以存在多个数据库,之前使用shell备份脚本,但是同一时刻只能备份一个数据库,对于几百G的备份文件,这个速度显然太慢,今天学习了Python多线程,刚好应用一下。
分析:1、Python多线程在某些场景上是鸡肋,但是这里使用多线程,目的是开启多个shell子进程。
2、磁盘I/O允许情况下,使用多个db2 backup进程。
3、thread模块有诸多问题,这里使用threading模块。
4、先前备份脚本修改端口来清理已连接应用,太过暴力,虽然都为冷备,但每次重启开销太大,这里使用db2 force application all。
5、如果第四步清理连接异常,那就无法进行备份,暂时未找到捕获异常的合适方式,待考虑,不过使用连续三次清理,不是特别情况,99.9%情况下是OK的。
6、可以不使用多线程,直接在使用subprocess开启多个子进程,这里是应用多线程,subprocess不在展示。
下面是具体代码:
MyThread.py
#!/usr/bin/env python
# encoding: utf-8
import threading
class MyThread(threading.Thread):
#Thread子类
def __init__(self,func,args,name=''):
threading.Thread.__init__(self)
self.name = name
self.func = func
self.args = args
def run(self):
self.func(*self.args)
db2backup.py
#!/usr/bin/env python
# encoding: utf-8
import threading
import logging
import commands
import sys
import MyThread
from time import ctime, sleep
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(filename)s[line:%(lineno)-1d] %(levelname)s %(message)s',
datefmt='%a, %d %b %Y %H:%M:%S',
filename='db2_backup.log',
filemode='a')
# logging.debug('This is debug message')
# logging.info('This is info message')
# logging.warning('This is warning message')
def db2_backup(inst_name, db_name, bak_dir):
#实现db2 备份
#检查实例用户
whoami = commands.getstatusoutput('whoami')
if whoami[1] != inst_name:
#print '用户身份有误,当前实例 %s,配置文件实例 %s' %(whoami,inst_name)
logging.error('用户身份有误,当前实例 %s,配置文件实例 %s' %(whoami,inst_name))
sys.exit()
#开始备份
cmd = 'db2 backup database %s to %s' % (db_name,bak_dir)
exec_res = commands.getstatusoutput(cmd)
if exec_res[0] == 0:
#print "%s 备份成功." % db_name
logging.info('% %s 备份成功.' % (ctime(),db_name))
print exec_res[1]
return exec_res
def read_conf(file_path):
#读取要备份的数据库配置
db_conf = []
with open(file_path,'r') as f:
for line in f:
line_list = line.strip().split(':')
if len(line_list) != 3:
logging.warning('%s 行配置不正确' % line.strip())
continue
cur_line = (line_list[0],line_list[1],line_list[2])
db_conf.append(cur_line)
return db_conf
def main():
db_conf = read_conf('database.cfg')
thread_num = len(db_conf)
#实例化线程
threads = []
for line in db_conf:
t = MyThread.MyThread(db2_backup,line,db2_backup.__name__)
threads.append(t)
#清除已建立连接
force_num = 3
while force_num:
commands.getstatusoutput('db2 force application all')
if force_num == 3:
sleep(1)
force_num -= force_num
#执行线程
for i in range(thread_num):
threads[i].start()
#等待线程同步,结束进程
for i in range(thread_num):
threads[i].join()
if __name__ == '__main__':
main()
要备份的数据库的配置信息:
database.cfg
实例名,数据库名,备份目录
db2inst1:PTEST:/home/db2inst1
db2inst1:PTEST2:/home/db2inst1