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 相关文章推荐
一则python3的简单爬虫代码
May 26 Python
python中私有函数调用方法解密
Apr 29 Python
详解python使用Nginx和uWSGI来运行Python应用
Jan 09 Python
python互斥锁、加锁、同步机制、异步通信知识总结
Feb 11 Python
20个常用Python运维库和模块
Feb 12 Python
详解python的sorted函数对字典按key排序和按value排序
Aug 10 Python
pyinstaller打包单个exe后无法执行错误的解决方法
Jun 21 Python
python中PS 图像调整算法原理之亮度调整
Jun 28 Python
Python实现Wordcloud生成词云图的示例
Mar 30 Python
Django 解决阿里云部署同步数据库报错的问题
May 14 Python
Sentry错误日志监控使用方法解析
Nov 12 Python
pymongo insert_many 批量插入的实例
Dec 05 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之CodeIgniter学习笔记
2013/06/17 PHP
thinkphp框架无限级栏目的排序功能实现方法示例
2020/03/29 PHP
input的focus方法使用
2010/03/13 Javascript
用js模拟JQuery的show与hide动画函数代码
2010/09/20 Javascript
解决Extjs4中form表单提交后无法进入success函数问题
2013/11/26 Javascript
直接在JS里创建JSON数据然后遍历使用
2014/07/25 Javascript
JavaScript对Cookie进行读写操作实例
2015/07/25 Javascript
基于JS实现EOS隐藏错误提示层代码
2016/04/25 Javascript
Bootstrap布局方式详解
2016/05/27 Javascript
Javascript中的arguments对象
2016/06/20 Javascript
你有必要知道的10个JavaScript难点
2017/07/25 Javascript
bootstrap日期插件daterangepicker使用详解
2017/10/19 Javascript
vue 使用 vue-pdf 实现pdf在线预览的示例代码
2020/04/26 Javascript
Threejs实现滴滴官网首页地球动画功能
2020/07/13 Javascript
vue+echarts实现动态折线图的方法与注意
2020/09/01 Javascript
JavaScript实现移动端拖动元素
2020/11/24 Javascript
Vue——前端生成二维码的示例
2020/12/19 Vue.js
[09:43]DOTA2每周TOP10 精彩击杀集锦vol.5
2014/06/25 DOTA
python生成随机图形验证码详解
2017/11/08 Python
OpenCV HSV颜色识别及HSV基本颜色分量范围
2019/03/22 Python
python如何将多个PDF进行合并
2019/08/13 Python
Python Django模板之模板过滤器与自定义模板过滤器示例
2019/10/18 Python
Python使用socket_TCP实现小文件下载功能
2020/10/09 Python
CSS3中Color的一些特性介绍
2012/05/27 HTML / CSS
浅析移动设备HTML5页面布局
2015/12/01 HTML / CSS
澳大利亚电子产品购物网站:Dick Smith
2017/02/02 全球购物
Java的类与C++的类有什么不同
2014/01/18 面试题
2014年父亲节活动方案
2014/03/06 职场文书
班级读书活动总结
2014/06/30 职场文书
销售顾问工作计划书
2014/09/15 职场文书
费城故事观后感
2015/06/10 职场文书
MySQL入门命令之函数-单行函数-流程控制函数
2021/04/05 MySQL
分布式Redis Cluster集群搭建与Redis基本用法
2022/02/24 Redis
python中的sys模块和os模块
2022/03/20 Python
Spring Data JPA框架自定义Repository接口
2022/04/28 Java/Android
Win11 Build 25179预览版发布(附更新内容+ISO官方镜像下载)
2022/08/14 数码科技