利用mysqldump导出数据库的子集

利用mysqldump导出数据库的子集

一、引言

假如:

  1. 你有一个非常大的正式数据库,和一个空的测试数据库
  2. 需要把正式数据库中的部分数据导到测试数据库中用来测试,同时,
  3. 希望导入的数据尽可能的保持一致性、完备性

比如,有一个商城的数据库,你希望导出其中的部分数据到测试数据库中,导入的两个主要依据是:

  • 用户表user:购买了商品的部分用户和没有购买商品的部分用户
  • 商品表goods:部分已经有过购买的商品和部分没人购买的商品

其他表(如订单order、浏览历史view_history则依据已经导出的user表和goods表导出,而诸如文章articles这类属于系统的表则可以独立地部分导出,有些系统配置的表(如shop_config)则需要全部导出。另外一些表你只希望导出空表,因为担心其中的记录会影响测试。

通过使用mysqldump工具的一些选项,通过管道配合mysql,利用shell脚本把这些命令组织起来,可以做到。

mysqldump相关选项:

  • -w选项

    指定导出的条件,相当于查询中指定的WHERE语句

  • -d`选项

    不导出数据,只导出表的定义。用于导出空表

  • -t选项

    -d选项相反,只导出数据,不导出表的定义。用来追加记录到已经存在的表。

    mysqldump默认会同时导出表的定义和数据

其它:

  • msyql-e选项

    用来执行一个sql语句组成的字符串,必须要用双引号包含起来

  • 管道操作符 |

    用来把前一个命令的输出作为后一个命令的输入

二、实现

导入数据的源数据库和目的数据库相关配置如下(已经写在shell脚本中):

#!/bin/bash

REMOTE_DBHOST=a.remote.com
REMOTE_DBNAME=shop
REMOTE_DBUSER=root
REMOTE_DBPASS=root

LOCAL_DBHOST=localhost
LOCAL_DBNAME=shop
LOCAL_DBUSER=root
LOCAL_DBPASS=root

REMOTE_ARGS=" -h${REMOTE_DBHOST} -u${REMOTE_DBUSER} -p${REMOTE_DBPASS} ${REMOTE_DBNAME}"
LOCAL_ARGS=" -h${LOCAL_DBHOST} -u${LOCAL_DBUSER} -p${LOCAL_DBPASS} ${LOCAL_DBNAME}"

第一步,筛选相关的用户id。

function selectUserId() {
  echo "select users ..."
  # 创建一个临时表来存储用户id
  mysql ${REMOTE_ARGS} -e "DROP TABLE IF EXISTS tmp_user_ids; CREATE TABLE tmp_user_ids(id INT NOT NULL PRIMARY KEY);"
  # 选择购买了商品的部分用户,最多导入100个哈
  mysql ${REMOTE_ARGS} -e "INSERT INTO tmp_user_ids SELECT DISTINCT user_id FROM `order` WHERE `status`=1 LIMIT 100"
  # 选择没有购买商品的部分用户,最多20个
  mysql ${REMOTE_ARGS} -e "INSERT INTO tmp_user_ids SELECT id FROM user WHERE id NOT IN (SELECT user_id FROM `order`) LIMIT 20"
}

第二步,导入用户表user以及用户的地址表address

function dumpUserTable() {
  mysqldump ${REMOTE_ARGS} user -w 'id IN (SELECT id FROM tmp_user_ids)' | mysql ${LOCAL_ARGS}
  mysqldump ${REMOTE_ARGS} address -w 'user_id IN (SELECT id FROM tmp_user_ids)' | mysql ${LOCAL_ARGS} 
}

第三步,导入用户的订单表order以及订单商品表order_goods

function dumpOrderTable() {
  mysqldump ${REMOTE_ARGS} order -w 'user_id IN (SELECT id FROM tmp_user_ids)' | mysql ${LOCAL_ARGS}
  # order的视图
  mysql ${REMOTE_ARGS} -e "CREATE VIEW view_order_tmp as SELECT * FROM `order` WHERE user_id IN (SELECT id FROM tmp_user_ids)"
  mysqldump ${REMOTE_ARGS} order_goods -w 'order_id IN (SELECT id view_order_tmp)' | mysql
  # order_goods的视图
  mysql ${REMOTE_ARGS} -e "CREATE VIEW view_order_goods_tmp as SELECT * FROM `order_goods` WHERE order_id IN (SELECT id view_order_tmp)"
}

第四步,导入商品表goods

function dumpGoodsTable() {
  # 导出出售过的商品
  mysqldump ${REMOTE_ARGS} goods -w 'id IN (SELECT goods_id FROM view_order_goods_tmp)' | mysql ${LOCAL_ARGS}
  # 导出未出售过的商品,限10个。因为追加,所以用-t选项
  mysqldump ${REMOTE_ARGS} goods -t -w 'id NOT IN (SELECT goods_id FROM view_order_goods_tmp) LIMIT 10' | mysql ${LOCAL_ARGS}
  # 未出售过商品的视图 
  mysql {$REMOTE_ARGS} -e "CREATE VIEW view_goods_tmp AS (SELECT * FROM goods WHERE id NOT IN (SELECT goods_id FROM view_order_goods_tmp) LIMIT 10)"
  # 导出商品的图片
  mysqldump ${REMOTE_ARGS} goods_images -w 'goods_id IN (SELECT goods_id FROM view_order_goods_tmp)' | mysql ${LOCAL_ARGS}
  mysqldump ${REMOTE_ARGS} goods_images -t -w 'goods_id IN (SELECT goods_id FROM view_goods_tmp)' | mysql ${LOCAL_ARGS}
}

第五步,导入其它表。

function dumpOtherTables() {
  # 导出10篇文章
  mysqldump ${REMOTE_ARGS} articles -w '1 LIMIT 50' | mysql ${LOCAL_ARGS}
  # 商城配置,全部导出
  mysqldump ${REMOTE_ARGS} shop_config | mysql ${LOCAL_ARGS}
  # 评论,导出空表
  mysqldump ${REMOTE_ARGS} comment -d | mysql ${LOCAL_ARGS}
}

第六步,清除远程服务器上的临时表和视图

function cleanTmpTableAndView() {
  mysql ${REMOTE_ARGS} -e "DROP TABLE tmp_user_ids;DROP VIEW view_goods_tmp;DROP VIEW view_order_goods_tmp;DROP VIEW view_order_tmp"
}

最后,把以上函数组织起来,运行

function main() {
  selectUsers;
  dumpUserTable;
  dumpOrderTable;
  dumpGoodsTable;
  dumpOtherTables;
  cleanTmpTableAndView;
}

# 运行
main

注意

  • 编写命令时必须清楚到底是命令针对的是远程的数据库还是在本地的数据库中操作,以免把本地数据库中的表与远程数据库中的表混在一起操作。
  • 若要避免过多的嵌套SELECT查询,可以在源数据库中先建立一个视图来辅助

三、总结

mysqldump还有其他很有用处的选项,可用mysqldump --help打印出帮助研究下。

说明:本篇文章的例子是根据真实用例改编而来的,真实的用例因为与工作相关,当然不可能原原本本的搬出来哈。真实的用例比这个要简单,不需要创建视图,不过表比较多,相同类型操作的表写在一个文件里,然后逐行读取操作。

猜你喜欢

转载自blog.csdn.net/chunyuan314/article/details/73226496
今日推荐