最近公司新项目上线,需要数据库搬迁,但新版本和老版本数据库差距比较大,关系也比较复杂。如果用传统办法,需要撰写很多mysql脚本,工程量虽然不大,但对于没有dba的公司来说,稍微有点难度。本人就勉为其难,用redis作为mysql中转站,先把原来的mysql数据转移到redis里面,再从redis转换到新的mysql。整个过程脉络清晰,脚本简单。

  首先,公司之前的项目是,flask+sqlalchemy的方式,直接复制原来的model文件,稍微修改一下,就有以下代码。

 # coding:utf-8
 from sqlalchemy import create_engine, ForeignKey, Column, Integer, String, Text, DateTime, Boolean, and_, or_,\
     SmallInteger, func, Numeric, select, Float, Table, TIMESTAMP, DECIMAL, desc
 from sqlalchemy.orm import relationship, backref, sessionmaker, scoped_session
 from sqlalchemy.ext.declarative import declarative_base
 from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method, Comparator
 from sqlalchemy import event
 import redis
 import json

 mysql_info = "mysql://username:password@ip_address:3306/databasename?charset=utf8"
 redis_store = redis.Redis(host='127.0.0.1', port=6380, password='password', db=5)

 engine = create_engine(mysql_info, pool_recycle=7200)
 Base = declarative_base()

 class User(Base):
     __tablename__ = 'user'

     id = Column('id', Integer, primary_key=True)
     phone_number = Column('phone_number', String(11), index=True)
     password = Column('password', String(30))
     nickname = Column('nickname', String(30), index=True, nullable=True)
     headpic = Column('headpic', String(100), nullable=True)
     register_time = Column('register_time', DateTime, index=True)
     email = Column('email', String(50), default='', index=True)
     real_name = Column('real_name', String(50), default='', index=True)
     user_admin = Column('user_admin', Integer, index=True, default=0)
     rc_token = Column('rc_token', String(100))
     device_token = Column('device_token', String(100), unique=True, nullable=True)
     unit_id = Column('unit_id', Integer, ForeignKey('unit.id'))
     unit = relationship("Unit", backref=backref('users'))

     def to_dict(self):
         return dict(id=self.id, phone_number=self.phone_number,
                     password=self.password, nickname=self.nickname,
                     headpic=self.headpic, register_time=self.register_time.strftime('%Y-%m-%d %H:%M:%S'),
                     user_admin=self.user_admin, rc_token=self.rc_token,
                     unit_id=self.unit_id, device_token=self.device_token,
                     )

 class Group(Base):
     __tablename__ = 'groups'

     id = Column('id', Integer, primary_key=True)
     name = Column('name', String(100), index=True)
     address = Column('address', String(100), index=True, nullable=True)
     contact_person = Column('contactperson', String(30), nullable=True)
     contact_number = Column('contactnumber', String(30), nullable=True)
     unit_id = Column('unit_id', Integer, ForeignKey('unit.id'))
     unit = relationship('Unit', backref=backref('groups'))

 class Monitor(Base):
     __tablename__ = 'monitor'

     id = Column('id', Integer, primary_key=True)
     u_id = Column('sn_num', String(10), index=True)
     phone_num = Column('phone_num', String(20), index=True, nullable=True)
     name = Column('name', String(40), index=True, nullable=True)
     position = Column('position', String(40), nullable=True)
     join_time = Column('join_time', DateTime, index=True, nullable=True)
     group_id = Column('group_id', Integer, ForeignKey('groups.id'))
     group = relationship("Group", backref=backref('monitors'))
     longitude = Column('longitude', DECIMAL(12, 9), default=31.000000)
     latitude = Column('latitude', DECIMAL(12, 9), default=121.000000)

     def to_dict(self):
         unit_id = self.group.unit_id
         return dict(id=self.id, u_id=self.u_id, phone_num=self.phone_num, name=self.name,
                     position=self.position, join_time=self.join_time.strftime('%Y-%m-%d %H:%M:%S'), unit_id=unit_id,
                     longitude=str(self.longitude), latitude=str(self.latitude))

 class Unit(Base):
     __tablename__ = 'unit'

     id = Column('id', Integer, primary_key=True)
     name = Column('name', String(100), index=True, nullable=True)
     address = Column('address', String(100), index=True, nullable=True)
     contact_person = Column('contactperson', String(30), index=True, nullable=True)
     contact_number = Column('contactnumber', String(30), nullable=True)
     device_operation_password = Column('device_operation_password', String(4), nullable=True)
     rc_group_id = Column('rc_group_id', String(50), index=True, nullable=True)
     rc_group_name = Column('rc_group_name', String(50), index=True, nullable=True)
     longitude = Column('longitude', DECIMAL(12, 9), nullable=True)
     latitude = Column('latitude', DECIMAL(12, 9), nullable=True)
     active = Column('active', SmallInteger, index=True, default=0)

     def to_dict(self):
         return dict(id=self.id, name=self.name, address=self.address,
                     contact_person=self.contact_person, contact_number=self.contact_number,
                     device_operation_password=self.device_operation_password,
                     rc_group_id=self.rc_group_id, rc_group_name=self.rc_group_name,
                     longitude=str(self.longitude), latitude=str(self.latitude), active=self.active)

 db_session = scoped_session(sessionmaker(autocommit=False,
                                          autoflush=False,
                                          bind=engine))

 Base.query = db_session.query_property()

 def old_sql_2_redis():
     redis_store.flushdb()
     units = Unit.query.all()
     [redis_store.rpush('units', json.dumps(unit.to_dict())) for unit in units]

     users = User.query.all()
     [redis_store.rpush('users', json.dumps(user.to_dict())) for user in users]

     monitors = Monitor.query.all()
     [redis_store.rpush('monitors', json.dumps(monitor.to_dict())) for monitor in monitors]

 if __name__ == '__main__':
     old_sql_2_redis()

把原来的数据库复制到本地redis了,看查看里面的元素。比如user数据,直接建一个user的list,每个appened其json格式的数据就可以了。主要注意点就是,如果新版本的表中没有的字段,就不要写入的redis了。

第二步就是把本地redis里面的数据,放到新的数据库上。这边要注意以下,把需要修改的地方要标示出来,可能加了其他字段,这些字段没有默认值的话,要自己添加上。过程也比较简单。

 # coding:utf-8
 from sqlalchemy import create_engine, ForeignKey, Column, Integer, String, Text, DateTime, Boolean, and_, or_,\
     SmallInteger, func, Numeric, select, Float, Table, TIMESTAMP, DECIMAL, desc
 from sqlalchemy.orm import relationship, backref, sessionmaker, scoped_session
 from sqlalchemy.ext.declarative import declarative_base
 from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method, Comparator
 from sqlalchemy import event
 import redis
 import json
 import datetime
 import uuid

 mysql_info = "mysql://username:password@ip_address:3306/database_name?charset=utf8"
 redis_store = redis.Redis(host='127.0.0.1', port=6380, password='password', db=5)

 engine = create_engine(mysql_info, pool_recycle=7200)
 Base = declarative_base()

 class User(Base):
     __tablename__ = 'user'

     id = Column('id', Integer, primary_key=True)
     phone_number = Column('phone_number', String(11), index=True)
     password = Column('password', String(30))
     nickname = Column('nickname', String(30), index=True, nullable=True)
     headpic = Column('headpic', String(100), nullable=True)
     register_time = Column('register_time', DateTime, index=True, default=datetime.datetime.now)
     user_admin = Column('user_admin', SmallInteger, index=True, default=0)
     hidden_user = Column('hidden_user', SmallInteger, index=True, default=0)
     rc_token = Column('rc_token', String(100), nullable=True)
     device_token = Column('device_token', String(100), unique=True, nullable=True)
     unit_id = Column('unit_id', Integer, ForeignKey('unit.id'))
     unit = relationship('Unit', backref=backref('users'))

 class Monitor(Base):
     __tablename__ = 'monitor'

     id = Column('id', Integer, primary_key=True)
     # device_type 1代表灭弧 2代表电气火灾
     device_type = Column('device_type', SmallInteger, index=True, default=1)
     u_id = Column('sn_num', String(10), index=True)
     phone_num = Column('phone_num', String(20), index=True, nullable=True)
     name = Column('name', String(40), index=True)
     position = Column('position', String(40), nullable=True)
     join_time = Column('join_time', DateTime, index=True)
     longitude = Column('longitude', DECIMAL(12, 9), default=31.000000)
     latitude = Column('latitude', DECIMAL(12, 9), default=121.000000)
     unit_id = Column('unit_id', Integer, ForeignKey('unit.id'))

 class Unit(Base):
     __tablename__ = 'unit'

     id = Column('id', Integer, primary_key=True)
     name = Column('name', String(100), index=True)
     address = Column('address', String(100), index=True, nullable=True)
     contact_person = Column('contactperson', String(30), nullable=True)
     contact_number = Column('contactnumber', String(30), nullable=True)
     device_operation_password = Column(')
     rc_group_id = Column('rc_group_id', String(36), default=str(uuid.uuid1()))
     rc_group_name = Column('rc_group_name', String(50), nullable=True)
     longitude = Column('longitude', DECIMAL(12, 9), default=31.000000)
     latitude = Column('latitude', DECIMAL(12, 9), default=121.000000)
     active = Column('active', SmallInteger, index=True, default=0)
     is_group = Column('is_group', SmallInteger, index=True, default=0)
     parent_id = Column('parent_id', Integer, ForeignKey('unit.id'))

 db_session = scoped_session(sessionmaker(autocommit=False,
                                          autoflush=False,
                                          bind=engine))

 Base.query = db_session.query_property()

 def redis_2_new_sql():
     units_json = redis_store.lrange('units', 0, -1)
     units = [Unit(is_group=0, parent_id=None, **json.loads(unit_json)) for unit_json in units_json]
     [db_session.add(unit) for unit in units]
     try:
         db_session.commit()
     except Exception as e:
         print e
         db_session.rollback()
         return

     users_json = redis_store.lrange('users', 0, -1)
     users = [User(hidden_user=0, **json.loads(uer_json)) for uer_json in users_json]
     [db_session.add(user) for user in users]
     try:
         db_session.commit()
     except Exception as e:
         print e
         db_session.rollback()
         return

     monitors_json = redis_store.lrange('monitors', 0, -1)
     monitors = [Monitor(**json.loads(monitor_json)) for monitor_json in monitors_json]
     [db_session.add(monitor) for monitor in monitors]
     try:
         db_session.commit()
     except Exception as e:
         print e
         db_session.rollback()
         return

 if __name__ == '__main__':
     redis_2_new_sql()

整个过程相当简单,需要注意的就是,前后顺序,因为user和monitor都有一个外键指向unit,所以要先恢复unit表,这样就不会出错了。

看来以后我有新方法搬迁数据库了。

利用redis协助mysql数据库搬迁的更多相关文章

  1. 用Redis作为Mysql数据库的缓存【转】

    用Redis作Mysql数据库缓存,必须解决2个问题.首先,应该确定用何种数据结构存储来自Mysql的数据:在确定数据结构之后,还要考虑用什么标识作为该数据结构的键. 直观上看,Mysql中的数据都是 ...

  2. 利用oneproxy部署mysql数据库的读写分离

    实验系统:CentOS 6.6_x86_64 实验前提:防火墙和selinux都关闭 实验说明:本实验共有4台主机,IP分配如拓扑 实验软件:mariadb-10.0.20 oneproxy-rhel ...

  3. 利用xtrabackup备份mysql数据库

    利用xtrabackup备份mysql数据库 一.安装1.直接下载二进制文件wget http://www.percona.com/downloads/XtraBackup/XtraBackup-2. ...

  4. 用Redis作Mysql数据库缓存

    使用redis作mysql数据库缓存时,需要考虑两个问题: 1.确定用何种数据结构存储来自Mysql的数据; 2.在确定数据结构之后,用什么标识作为该数据结构的键. 直观上看,Mysql中的数据都是按 ...

  5. redis(二)--用Redis作MySQL数据库缓存

    用Redis作MySQL数据库缓存,必须解决2个问题.首先,应该确定用何种数据结构存储来自mysql的数据:在确定数据结构之后,还要考虑用什么标识作为该数据结构的键. 直观上看,Mysql中的数据都是 ...

  6. 利用Java进行MySql数据库的导入和导出

    利用Java来进行Mysql数据库的导入和导出的总体思想是通过Java来调用命令窗口执行相应的命令. MySql导出数据库的命令如下: mysqldump -uusername -ppassword  ...

  7. node.js利用express连接mysql数据库

    我们创建一个mysql.js (好像大神们,称呼这叫一个模块,然后暴露一个接口)用来连接数据库 var connction ={}; connction.mysql = { host:"lo ...

  8. 利用NHibernate与MySQL数据库交互

    本文章使用Visual Studio作为开发工具,并建立在已经安装MySQL数据库的前提. NHibernate是一个面向.NET环境的对象/关系数据库映射工具.官网:http://nhibernat ...

  9. 利用Python操作MySQL数据库

    前言 在工作中,我们需要经常对数据库进行操作,比如 Oracle.MySQL.SQL Sever 等,今天我们就学习如何利用Python来操作 MySQL 数据库. 本人环境:Python 3.7.0 ...

随机推荐

  1. 在Ubuntu14.04下安装运行Unity-tweak-tool报错scheme missing的解决办法

    问题: 安装完unity-tweak-tool后,打开运行弹出出错窗口,忘了截图了,提示内容: scheme missing! Error: schema com.canonical.indicato ...

  2. 路由器WDS桥接教程

    因为有吧友买了此款路由又不会桥接,因此做这个教程.老鸟自动路过,废话不多说,下面开始讲解. 1.wifi密码破解和路由器用户名和密码部分请自行解决,我只讲桥接部分.首先,在浏览器里输入192.168. ...

  3. SJA1000寄存器设置

    在设置CAN控制器SJA1000的输出控制寄存器(OCR)时,由于电路图中只用到了TX0和RX0,所以只考虑OCTP0,OCTN0,OCPOL0.这里设置成了010.然后查了一下配置的表,如下所示: ...

  4. 一个简单的以User权限启动外部应用程序

    BOOL ExecuteAsUser(LPCWSTR lpszUserName, LPCWSTR lpszPassword, LPCWSTR lpszApplication, LPCWSTR lpsz ...

  5. PHP PDO 安装使用

    PDO(PHP Data Object) 是PHP 5新出来的东西,在PHP 6都要出来的时候,PHP 6只默认使用PDO来处理数据库,将把所有的数据库扩展移到了PECL,那么默认就是没有了我们喜爱的 ...

  6. 64位linux中使用inet_ntoa报错处理

    最近一直使用linux mint 15,我用的是64位操作系统,在进行网络编程的时候,发现一个问题,请看源码: /*get_ip_by_name.c*/ #include <stdio.h> ...

  7. USBSpirit(USB精灵)更新到1.2.300.105

    USBSpirit(USB精灵)是CopyU!的内核引擎,CopyU!的主要功能均由该引擎提供,此次更新主要内容如下:(版本号:1.2.300.105) 1.[修复]:修复了几处引擎的资源泄露问题,提 ...

  8. COJ 1010 WZJ的数据结构(十) 线段树区间操作

    传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=1001 WZJ的数据结构(十) 难度级别:D: 运行时间限制:3000ms: ...

  9. cxgrid按条件计算合计值 TcxTreeList计算合计值

    在Footer的第一列显示[合计:] 加一个Summary项,Column设为Grid的第一列,Kind设为skNone 在该Summary项的OnGetText事件中,输入: procedure T ...

  10. codevs1033 蚯蚓的游戏问题

    题目描述 Description 在一块梯形田地上,一群蚯蚓在做收集食物游戏.蚯蚓们把梯形田地上的食物堆积整理如下: a(1,1)  a(1,2)…a(1,m) a(2,1)  a(2,2)  a(2 ...