python实现不同数据库间数据同步功能


Posted in Python onFebruary 25, 2021

功能描述

数据库间数据同步方式很多,在上篇博文中有总结。本文是用py程序实现数据同步。
A数据库中有几十张表,要汇聚到B数据库中,且表结构一致,需要准实时的进行数据同步,用工具实现时对其控制有限且配置较繁琐,故自写程序,可自由设置同步区间,记录自己想要的日志

代码

本代码实现功能简单,采用面向过程,有需求的同学可以自己优化成面向对象方式,在日志这块缺少数据监控,可根据需求增加。主要注意点:
1、数据抽取时采用区间抽取(按时间区间)、流式游标迭代器+fetchone,避免内存消耗
2、在数据插入时采用executemany(list),加快插入效率

import pymysql
import os
import datetime,time

def update_time(content):
  with open(filepathtime, 'w') as f:
    f.writelines(content)

def recode_log(content):
  with open(filepathlog, 'a') as f:
    f.writelines(content)

def transferdata():
  #1、获取需要抽取的表,抽取数据的时间点
  with open(filepathtime, 'r') as f:
    lines = f.readlines() # 读取所有数据
    print("需要同步的表信息",lines)
    for line in lines:
      startdatetime = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
      tablename_list =line.split(',')
      #print(tablename_list)
      #print(tablename_list[-1])
      tablename_list[-1] = tablename_list[-1].replace('\n','')
      #print(tablename_list)
      tablename = tablename_list[0]
      updatetime = tablename_list[1]
      #print(tablename,updatetime)

      #2、抽取此表此时间点的数据,同步
      updatetime_s = datetime.datetime.strptime(updatetime, '%Y-%m-%d %H:%M:%S')
      updatetime_e = (updatetime_s + datetime.timedelta(hours=1)).strftime("%Y-%m-%d %H:%M:%S")
      #print(updatetime_s)
      #print(q_sql)
      db = pymysql.connect(host=host_o, port=port_o, user=user_o, passwd=passwd_o, db=db_o)
      cursor = db.cursor()
      q_sql = "select a,b,c from %s where c >= '%s' " % \
          (tablename, updatetime_s)
      #2.1 首先判断下原表中是否有待同步数据,若有则同步且更新同步的时间参考点,若没有则不同步且不更新同步的时间参考点
      try:
        cursor.execute(q_sql)
        results = cursor.fetchone()
        #print(results) #返回是元组
        #print("查询原表数据成功!",tablename)
      except BaseException as e:
        print("查询原表数据失败!",tablename, str(e))
        #记录异常日志
        updatetime_n = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
        eachline_log = updatetime_n + '[erro]:' + tablename + str(e) + '\n'
        content_log.append(eachline_log)
        recode_log(content_log)
      db.close()

      if results:
        print("===============================================================================")
        print("有数据可同步",tablename)
        db = pymysql.connect(host=host_o, port=port_o, user=user_o, passwd=passwd_o, db=db_o, charset='utf8', cursorclass=pymysql.cursors.SSDictCursor)
        cursor = db.cursor()
        q_sql1 = "select a,b,c from %s where c >= '%s' and c < '%s' " % \
             (tablename, updatetime_s, updatetime_e)
        #print(q_sql1)
        result_list = []
        try:
          # startdatetime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
          cursor.execute(q_sql1)
          #results = cursor.fetchall()
          # enddatetime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
          # print(results) #返回是元组
          #使用流式游标迭代器+fetchone,减少内存消耗
          while True:
            result = cursor.fetchone()
            if not result:
              print("此区间无数据", q_sql1)
              break
            else:
              one_list = list(result.values())
              # print(result_list)
              result_list.append(one_list)
          print(result_list) #返回是列表
          #print("查询数据成功!", tablename)
        except BaseException as e:
          print("查询数据失败!", tablename, str(e))
          # 记录异常日志
          updatetime_n = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
          eachline_log = updatetime_n + '[erro]:' + tablename + str(e) + '\n'
          content_log.append(eachline_log)
          recode_log(content_log)
        db.close()

        results_len = (len(result_list))
        if results_len>0:
          #3、将数据插入到目标表中,利用list提高插入效率
          i_sql = "insert into table_t(a,b,c) values (%s,%s,%s)"
          #print(i_sql)
          db = pymysql.connect(host=host_d, port=port_d, user=user_d, passwd=passwd_d, db=db_d)
          cursor = db.cursor()
          try:
            #startdatetime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
            cursor.executemany(i_sql, result_list)
            db.commit()
            #enddatetime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
            print("插入成功!",tablename)
          except BaseException as e:
            db.rollback()
            print("插入失败!", tablename,str(e))
            #记录异常日志
            updatetime_n = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
            eachline_log = updatetime_n + '[erro]:' + tablename + str(e) + '\n'
            content_log.append(eachline_log)
            recode_log(content_log)
          db.close()
        enddatetime = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))

        #4、如果有数据同步,则更新参考点时间为下一个节点时间
        eachline_time = tablename+','+updatetime_e+'\n' #此时间点是下一个时间点updatetime_e
        content_time.append(eachline_time)
        print("更新表时间点",content_time)

        # 5、记录成功日志
        eachline_log = enddatetime + '[success]:' + tablename + '开始时间' + startdatetime + \
          '结束时间' + enddatetime + ',同步数据量'+str(results_len)+',当前参考点' + updatetime_e + '\n'
        content_log.append(eachline_log)
        print("日志信息",content_log)
        #print("===============================================================================")
      else:
        print("===============================================================================")
        print("无数据可同步",tablename)
        #db.close()
        enddatetime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
        # 4、如果无数据同步,则参考点时间不更新
        eachline_time = tablename + ',' + updatetime + '\n' #此时间点还是原时间updatetime
        content_time.append(eachline_time)
        print("不更新表时间点",content_time)

        # 5、成功日志信息
        eachline_log = enddatetime + '[success]:' + tablename + '开始时间' + startdatetime + \
          '结束时间' + enddatetime + ',同步数据量0'+ ',当前参考点' + updatetime_e + '\n'
        content_log.append(eachline_log)
        print("日志信息",content_log)
        #print("===============================================================================")

    #更新配置文件,记录日志
    update_time(content_time)
    recode_log(content_log)

if __name__ == '__main__':
  filepathtime = 'D:/test/table-time.txt'
  filepathlog = 'D:/test/table-log.txt'
  host_o = 'localhost'
  port_o = 3306
  user_o = 'root'
  passwd_o = 'root@123'
  db_o = 'csdn'
  host_d = 'localhost'
  port_d = 3306
  user_d = 'root'
  passwd_d = 'root@123'
  db_d = 'csdn'
  content_time = []
  content_log = []
  transferdata()

  #每5分钟执行一次同步
  # while True:
  #   transferdata()
  #   time.sleep(300)

table-time.txt配置文件,格式说明:
每行包括源库表名、此表的最小时间time,以逗号分隔
若多个表,可配置多个时间
每次脚本执行后,同步更新时间time。时间间隔设置为1小时,可根据情况在updatetime_e中对增量进行修改

table-log.txt
记录每次同步任务执行的结果,或执行中发生异常的日志
此文件需要定期进行清理

到此这篇关于python实现不同数据库间数据同步功能的文章就介绍到这了,更多相关python实现数据同步内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python中的Matplotlib模块入门教程
Apr 15 Python
通过数据库对Django进行删除字段和删除模型的操作
Jul 21 Python
Python实现简单的代理服务器
Jul 25 Python
python八大排序算法速度实例对比
Dec 06 Python
python+pillow绘制矩阵盖尔圆简单实例
Jan 16 Python
python最长回文串算法
Jun 04 Python
使用Python批量修改文件名的代码实例
Jan 24 Python
numpy库与pandas库axis=0,axis= 1轴的用法详解
May 27 Python
python求质数列表的例子
Nov 24 Python
Django ModelForm操作及验证方式
Mar 30 Python
python 30行代码实现蚂蚁森林自动偷能量
Feb 08 Python
k-means & DBSCAN 总结
Apr 27 Python
使用python实现学生信息管理系统
Feb 25 #Python
pytho matplotlib工具栏源码探析一之禁用工具栏、默认工具栏和工具栏管理器三种模式的差异
Feb 25 #Python
使用tkinter实现三子棋游戏
Feb 25 #Python
python matplotlib工具栏源码探析二之添加、删除内置工具项的案例
Feb 25 #Python
python matplotlib工具栏源码探析三之添加、删除自定义工具项的案例详解
Feb 25 #Python
python实现简单文件读写函数
Feb 25 #Python
python pygame 愤怒的小鸟游戏示例代码
Feb 25 #Python
You might like
php引用地址改变变量值的问题
2012/03/23 PHP
详解PHP+AJAX无刷新分页实现方法
2015/11/03 PHP
PHP实现一个多功能购物网站的案例
2017/09/13 PHP
Laravel 微信小程序后端搭建步骤详解
2019/11/26 PHP
js模拟滚动条(横向竖向)
2013/02/22 Javascript
JS中for循序中延迟加载动态效果的具体实现
2013/08/18 Javascript
JavaScript检测浏览器cookie是否已经启动的方法
2015/02/27 Javascript
JavaScript实现列表分页功能特效
2015/05/15 Javascript
在JavaScript中操作时间之setYear()方法的使用
2015/06/12 Javascript
使用控制台破解百小度一个月只准改一次名字
2015/08/13 Javascript
jQuery对象的链式操作用法分析
2016/05/10 Javascript
jQuery使用经验小技巧(推荐)
2016/05/31 Javascript
AngularJS 获取ng-repeat动态生成的ng-model值实例详解
2016/11/29 Javascript
react开发中如何使用require.ensure加载es6风格的组件
2017/05/09 Javascript
React 无状态组件(Stateless Component) 与高阶组件
2018/08/14 Javascript
解决Vue使用swiper动态加载数据,动态轮播数据显示白屏的问题
2018/09/27 Javascript
基于layui框架响应式布局的一些使用详解
2019/09/16 Javascript
layer弹窗在键盘按回车将反复刷新的实现方法
2019/09/25 Javascript
jQuery插件实现图片轮播效果
2020/10/19 jQuery
Element-ui 自带的两种远程搜索(模糊查询)用法讲解
2021/01/29 Javascript
Python使用scrapy抓取网站sitemap信息的方法
2015/04/08 Python
详解Python如何生成词云的方法
2018/06/01 Python
解决python ogr shp字段写入中文乱码的问题
2018/12/31 Python
详解python之heapq模块及排序操作
2019/04/04 Python
seek引发的python文件读写的问题及解决
2019/07/26 Python
python微信公众号开发简单流程实现
2020/03/09 Python
浅谈three.js中的needsUpdate的应用
2012/11/12 HTML / CSS
是否可以从一个static方法内部发出对非static方法的调用?
2014/08/18 面试题
写给爸爸的道歉信
2014/01/15 职场文书
民族团结先进个人材料
2014/02/05 职场文书
巴西世界杯32强口号
2014/06/05 职场文书
办公室领导干部作风整顿个人整改措施
2014/09/17 职场文书
社会工作专业自荐信
2014/09/26 职场文书
工商局领导班子存在的问题整改措施思想汇报
2014/10/05 职场文书
大学生团日活动总结
2015/05/06 职场文书
如何使用分区处理MySQL的亿级数据优化
2021/06/18 MySQL