MySQL简单技巧(三):教你轻松用information_schema表+python实现表结构同步(上)——理论篇

前文

  为了打通开发、测试、生产环境的MySQL数据库表一致性,以及减少研发的操作,比如需要上线一个功能,那就需要在三个环境都修改表,一方面带来繁琐的操作;另一方面当测试测成功上线时,总发现自己遗忘了某某表的修改,这无疑给项目的整个迭代发布带来了巨大的麻烦。所以引入数据表结构同步功能,来实现三套环境的表结构一致,对加速程序的开发迭代也是重要的一环。
  于是去年在领导的要求下基于Python实现了一套表结构工具,当时未找到相关的开源软件而只能自己造轮子,并且在轮子造完后就发现了2套开源表结构同步工具,一套基于go,一套基于Python,还是比较可惜!这里分享下我基于information_schema这个库所实现的表结构功能,相关代码会放到github上。
  以下是两套开源的表结构同步:

  我实现的这套相对简单易操作,当然也有许多需要完善的地方,有兴趣的小伙伴儿可以一起探讨。这套表结构代码是基于库以表为单位,比较不同库下的表结构差异,并且仅实现了字段、索引的同步,其他比如分区相关的就未具备同步功能。

什么是information_schema

  MySQL自带四个库,分别是sys、mysql、information_schema、performance_schema,后两者分别掌管着MySQL的数据库信息和性能信息,这个数据库信息就是我们需要的,所以锁定information_schema来实现表结构同步。通过show tables可以看到:
在这里插入图片描述
  可以看到自带的表是非常多的,包括字符编码(charset)、引擎(engine)、账号信息(session)、各色的权限(privileges)等等,但这些都和表结构同步无关,所以只要围绕以下四个表就行了:

  1. SCHEMATA:即schemata,记录了所有数据库的基本信息,即库名、编码
  2. TABLES:即tables,记录了所有数据表的基本信息,包括库名、表名、编码、引擎等
  3. COLUMNS:即columns,记录了所有字段的基本信息,包括库名、表名、字段名、字段类型、字段编码等
  4. STATISTICS:即statistics,记录了所有索引的基本信息,包括库名、表名、索引名、索引字段等

  接下来我会介绍在这些表里相关的字段信息,不过一些无用的字段我就不会跳过了,如果你对所有字段都很有兴趣的话,可以查看官网:MySQL官网介绍information_schema

SCHEMATA介绍

  首先看schemata,这个跟库相关的信息非常的简单(下面仅展示有用的字段),仅仅是库相关的编码和库名,而库不是我们比较的单位,所以这个库基本了解就行:
在这里插入图片描述

字段介绍
SCHEMA_NAME数据库名
DEFAULT_CHARACTER_SET_NAME数据库对应的字符编码,即charset
DEFAULT_COLLATION_NAME数据库对应的比较规则,即collation
TABLES介绍

  关于tables有许多表自带的属性,比如版本(.frm file version,8.0已废弃未使用)、行格式(row_format)、行数据平均估值(avg_row_length)、当前自增值(Auto_increment)等等对于表结构对比是无用的,可以忽视。重要的都归结在表格里。
在这里插入图片描述

字段介绍
TABLE_SCHEMA数据库名
TABLE_NAME数据表名
ENGINE数据表引擎,比如memory、engine、myisam
TABLE_COLLATION数据表字符编码+字符规则,比如utf8_general_ci,前缀utf8即编码
TABLE_COMMENT数据表注释

  由于此次代码未实现关于表编码、注释、引擎的对比,所以不详细介绍这块,不过基于这块,所涉及字段较少,可以很轻松的实现表相关的字段对比!

COLUMNS介绍

  columns表即是跟MySQL字段相关的,不过其中也涉及了很多跟表结构无关的字段,比如CHARACTER_MAXIMUM_LENGTH(字符串字段,字符的最大长度)、CHARACTER_OCTET_LENGTH(字符串字段,数据的最大长度)这类的,详细如下:
在这里插入图片描述
太多字段记不住,只要注意以下几个字段即可:

字段介绍
TABLE_SCHEMA数据库名
TABLE_NAME数据表名
COLUMN_NAME字段名
ORDINAL_POSITION字段位于表里的顺序,从1、2依次往下排
COLUMN_DEFAULT字段默认值
IS_NULLABLE字段是否为空,值为yes、no
DATA_TYPE字段类型,比如varchar
CHARACTER_SET_NAME字段编码,比如utf8
COLLATION_NAME字段比较规则编码,比如utf8_general_ci
COLUMN_TYPE字段类型,相对于DATA_TYPE多出了精度和其他信息,比如varchar(32)
COLUMN_KEY当前字段的索引类型,无则空,有比如:PRI、MUL
EXTRA一些其他信息,比如auto_increment、timestamp类型on update CURRENT_TIMESTAMP
COLUMN_COMMENT字段默认值

  可以看到字段有12个之多,那如果生成的sql要根据12个字段来比较并生成可见是非常麻烦的,这里可以借助set的对称差集^来做,如果有差集则说明二者有不同的地方(也可以借助hash对所有字段哈希取值进行比较),这个会在后文代码处介绍。然后有不同就通过modify来实现字段的变更。所以重点关注COLUMN_NAME(字段名)、COLUMN_TYPE(字段类型)、IS_NULLABLE(是否not null)、COLUMN_DEFAULT(是否有默认值)、EXTRA(是否有auto_increment或其他)、COLUMN_COMMENT(是否有字段注释),根据这些字段,就能轻松的拼凑一条modify语句!

STATISTICS介绍

  来聊聊索引的statistics,详细字段如下图,其中比如CARDINALITY用来统计该索引的不重复值、SEQ_IN_INDEX(索引顺序)这类的对表结构帮助不大的都可剔除:
在这里插入图片描述
总结需要记录的字段如下:

字段介绍
TABLE_SCHEMA数据库名
TABLE_NAME数据表名
NON_UNIQUE是否唯一索引,0为唯一,1为普通索引
INDEX_SCHEMA索引所在的数据库,和table_schema一致
INDEX_NAME索引名
SEQ_IN_INDEX索引所在位置,等同于ORDINAL_POSITION,也是从1开始排序
COLUMN_NAME索引所在的字段
COLLATION索引里的字段排序规则
CARDINALITY索引里的不重复值预估
SUB_PART前缀索引的部分,比如idx_age(10),就是括号的10,取前10个字符
NULLABLE字段是否可以为空
INDEX_TYPE索引类型:BTREE, FULLTEXT, HASH, RTREE
INDEX_COMMENT人为加的索引注释

  虽然涉及的字段也很多,不过扣除COLLATION、INDEX_COMMENT这种关系不大的字段,只要记住INDEX_NAME(索引名)、COLUMN_NAME(索引所在字段)、NON_UNIQUE(是否唯一索引)、SUB_PART(是否是前缀索引)这几个字段就能拼凑出一条add index的语句,而index_type这种可以强制要求btree索引才进行表结构同步,当然你也可以根据你的需求来获取你所需的字段进行比对!

表结构同步的基本原理

  表结构同步是为了比对开发、测试、生产乃至多个环境间的表差异,那么我们的比对可以以表为单位,一次可以选取多个表来完成。并且因为只是环境件的差异,所以比对的库名和表名必须一致!针对目标环境未存在的表,则生成创建语句。具体步骤如下:

  1. 连接:选定本地库和目标库的ip、port、database、user、pass来进行连接
  2. 保存:同时获取远程和本地的columns、statistics、tables的结果并存储
  3. 选择:本地选定需要比对的表,可以是单表或者多表
  4. 是否比对:如果是单表,寻找目标库是否有,有则进行比对环节,无则生成创建语句(基于show create table生成);如果是多表,可逐一遍历,然后进行单表的判断
  5. 比对环节:for循环遍历本地表所有字段,将字段逐一去目标表的字段遍历查找(由于单表字段一般不超过50,所以即使双重for,效率影响也不大);没找到,生成add语句;找到了,通过set比对差集,如果存在差集生成modify语句,不存在则表明一致!基于index的也一样,区别是index没有modify语句,所以可以通过drop+add的形式来更改索引名,也就是删除原来的索引树并新建一颗索引树!
  6. 合并:将所有生成的sql以逗号合并,形成针对一张表修改的sql语句;再将所有表的sql语句通过分号合并,生成针对所选表的修改。

  所以,手动实现一套表结构对比也不是特别难。而针对网上已存在的,很难定制出自己所需要的,比如add…after…这类的,很多开源工具不支持,而如果公司着实需要的话,就可以根据ORDINAL_POSITION这个字段来生成,这就显得非常灵活。

总结

  关于表结构同步理论篇就介绍到这,下篇记录代码实战,而关于这块还有很多待完善的,也希望大家多提建议~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值