一、前言

最近在做离线数据导入HBase项目,涉及将存储在Mysql中的历史数据通过bulkload的方式导入HBase。由于源数据已经不在DB中,而是以文件形式存储在机器磁盘,此文件是mysqldump导出的格式。如何将mysqldump格式的文件转换成实际的数据文件提供给bulkload作转换,是需要考虑的一个问题。

二、思路

我们知道mysqldump导出的文件主要是Insert,数据库表结构定义语句。而要解析的对象也主要是包含INSERT关键字记录,这样我们就把问题转换成如何从dmp文件解析Insert语句。接触过dmp文件的同学应该了解,其INSERT语句的结构,主要包含表名、字段名、字段值, 这里面主要包含几个关键字:INSERT INTO, VALUES。我们要做的就是把Values括号后的字段值给解析出来,这个过程需要考虑VALUES后面包含的是多少行的记录,有可能导出的记录Values后面包含多行对应mysql中存储的记录。

在解析文件过程中,我自然想到用Python来写,因为Python在处理文件方面有很多优势,也比较简单。在处理DMP文件这块,考虑到字段值间是用逗号分割的,在python中正好一个模块可以很好的来处理此类格式 ,即大家很熟悉的CSV模块,在处理CSV类型的文件有很多优势。在这里我们把CSV模块有在解析dmp文件,同时加一些解析逻辑,可以很好解决此类问题。

同时,我们要处理的dmp文件是经过压缩的,并且单个文件都比较大,都是Gigbytes的,在读取时需要注意机器内存大小,不能一次读出所有的数据,python也考虑到此类问题,采用的方法是惰性取值,即在真正使用时才从磁盘中加载相应的文件数据。如果想加块解析,还可以采集多进程或多线程的方法。

三、方法

处理流程图如下所示:

代码如下图所示:

  1. #!/usr/bin/env python
  2. import fileinput
  3. import csv
  4. import sys
  5. import gzip
  6.  
  7. # 设定CSV读取的最大容量
  8. csv.field_size_limit(sys.maxsize)
  9.  
  10. def check_insert(line):
  11. """
  12. 返回语句是否以insert into开头,如果是返回true,否则返回false
  13. """
  14. return line.startswith('INSERT INTO') or False
  15.  
  16. def get_line_values(line):
  17. """
  18. 返回Insert语句中包含Values的部分
  19. """
  20. return line.partition('VALUES ')[2]
  21.  
  22. def check_values_style(values):
  23. """
  24. 保证INSERT语句满足基本的条件,即包含(右括号
  25. """
  26.  
  27. if values and values[0] == '(':
  28. return True
  29. return False
  30.  
  31. def parse_line(values):
  32. """
  33. 创建csv对象,读取INSERT VALUES 字段值
  34. """
  35. latest_row = []
  36.  
  37. reader = csv.reader([values], delimiter=',',
  38. doublequote=False,
  39. escapechar='\\',
  40. quotechar="'",
  41. strict=True
  42. )
  43.  
  44. for reader_row in reader:
  45. for column in reader_row:
  46. # 判断字段值是否为空或为NULL
  47. if len(column) == 0 or column == 'NULL':
  48. latest_row.append("")
  49. continue
  50.  
  51. # 判断字段开头是否以(开头,如果是则说明此VALUES后面不只包含一行数据,可能有多行,要分别解析
  52. if column[0] == "(":
  53. new_row = False
  54. if len(latest_row) > 0:
  55. #判断行是否包含),如果包含则说明一行数据完毕
  56. if latest_row[-1][-1] == ")":
  57. # 移除)
  58. latest_row[-1] = latest_row[-1][:-1]
  59. if latest_row[-1] == "NULL":
  60. latest_row[-1] = ""
  61. new_row = True
  62. # 如果是新行,则打印该行
  63. if new_row:
  64. line="}}}{{{".join(latest_row)
  65. print "%s<{||}>" % line
  66. latest_row = []
  67.  
  68. if len(latest_row) == 0:
  69. column = column[1:]
  70.  
  71. latest_row.append(column)
  72. # 判断行结束符
  73. if latest_row[-1][-2:] == ");":
  74. latest_row[-1] = latest_row[-1][:-2]
  75. if latest_row[-1] == "NULL":
  76. latest_row[-1] = ""
  77.  
  78. line="}}}{{{".join(latest_row)
  79. print "%s<{||}>" % line
  80.  
  81. def main():
  82.  
  83. filename=sys.argv[1]
  84. try:
  85. #惰性取行
  86. with gzip.open(filename,"rb") as f:
  87. for line in f:
  88. if check_insert(line):
  89. values = get_line_values(line)
  90. if check_values_style(values):
  91. parse_line(values)
  92. except KeyboardInterrupt:
  93. sys.exit(0)
  94.  
  95. if __name__ == "__main__":
  96. main()

四、总结

总的说来,主要是利用Python的CSV模块来解析DMP文件的INSERT语句,如果DMP文件不规整,可能还是有些问题。对于dmp文件很大情况,也是需要考虑解析时间效率问题,可以考虑增加多进程或多线程机制。

如何用python解析mysqldump文件的更多相关文章

  1. Python解析Wav文件并绘制波形的方法

    资源下载 #本文PDF版下载 Python解析Wav文件并绘制波形的方法 #本文代码下载 Wav波形绘图代码 #本文实例音频文件night.wav下载 音频文件下载 (石进-夜的钢琴曲) 前言 在现在 ...

  2. Python解析excel文件并存入sqlite数据库

    最近由于工作上的需求 需要使用Python解析excel文件并存入sqlite 就此做个总结 功能:1.数据库设计 建立数据库2.Python解析excel文件3.Python读取文件名并解析4.将解 ...

  3. python解析ini文件

    python解析ini文件 使用configparser - Configuration file parser sections() add_section(section) has_section ...

  4. 如何用Python判断一个文件是否被占用?

    本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理 今天有同学问,用os模块的access()能否判断一个文件是否被占用?直觉上,这是行不通的,因为ac ...

  5. python 解析xml 文件: Element Tree 方式

    环境 python:3.4.4 准备xml文件 首先新建一个xml文件,countries.xml.内容是在python官网上看到的. <?xml version="1.0" ...

  6. python 解析xml 文件: DOM 方式

    环境 python:3.4.4 准备xml文件 首先新建一个xml文件,countries.xml.内容是在python官网上看到的. <?xml version="1.0" ...

  7. python 解析xml 文件: SAX方式

    环境 python:3.4.4 准备xml文件 首先新建一个xml文件,countries.xml.内容是在python官网上看到的. <?xml version="1.0" ...

  8. 遍历文件 创建XML对象 方法 python解析XML文件 提取坐标计存入文件

    XML文件??? xml即可扩展标记语言,它可以用来标记数据.定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言. 里面的标签都是可以随心所欲的按照他的命名规则来定义的,文件名为roi.xm ...

  9. Python解析HDF文件 分类: Python 2015-06-25 00:16 743人阅读 评论(0) 收藏

    前段时间因为一个业务的需求需要解析一个HDF格式的文件.在这之前也不知道到底什么是HDF文件.百度百科的解释如下: HDF是用于存储和分发科学数据的一种自我描述.多对象文件格式.HDF是由美国国家超级 ...

随机推荐

  1. HDU 3271 数位dp+二分

    SNIBB Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  2. Docker图形界面管理之DockerUI

    DockerUI DockerrUI是一个基于Docker API提供图形化页面简单的容器管理系统,支持容器管理.镜像管理. 1.1 下载镜像 docker pull abh1nav/dockerui ...

  3. 字典的setdefault() 和get()方法比较

    Python 字典 setdefault() 函数 和get() 类似: 如果键存在字典中,返回其value值 如果键不存在字典中,创建键值对.完后,返回值为默认值. 话不多说,上栗子: setdef ...

  4. T51071 Tony到死都想不出の数学题

    T51071 Tony到死都想不出の数学题 自己摘的题出了数据挂一下链接 \(a, b\) 均为整数 设 \(M(a)\) 为满足 \((a + b) | ab\) 的 \(b\) 的个数, 求 \( ...

  5. [Web] Web请求过程之二:DNS 域名解析

    一.域名解析过程 1.浏览器检查缓存,域名缓存时间可以通过 TTL 属性来设置. 2.如果浏览器缓存中没有,浏览器会去查找操作系统缓存中是否有这个域名对应的 DNS 解析结果.如果要设置域名对应的 I ...

  6. IOS取消performSelector警告

    #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks&quo ...

  7. VS2010 中更改项目名称

    Time.vcxproj修改项目名称,主要是通过以下几个步骤就能完成: 修改解决方案的名称. 修改解决项目名称. 修改项目的程序集名称和默认命名空间 替换整个项目或解决方案中的出现该名称的地方. 修改 ...

  8. Linux6.x修改出eth0网卡的解决方法

    1. 编辑70-persistent-net配置文件: # -persistent-net.rules 如果没有就新建一个,添加如下内容: # PCI device 0x14e4:0x165f (tg ...

  9. How To Configure VMware fencing using fence_vmware_soap in RHEL High Availability Add On——RHEL Pacemaker中配置STONITH

    本文主要简单介绍一下如何在RHEL 7 Pacemaker中配置一个fence_vmware_soap类型的STONITH设备(仅供测试学习). STONITH是Shoot-The-Other-Nod ...

  10. POJ 1986 Distance Queries (Tarjan算法求最近公共祖先)

    题目链接 Description Farmer John's cows refused to run in his marathon since he chose a path much too lo ...