Hive元数据升级工具源码剖析——HiveSchemaTool

1 背景

随着公司业务的井喷式发展,数仓元数据也日益庞大,尤其是存在很多设计不合理的大分区表,导致一些元数据表(如PARTITIONS,PARTITION_PARAMS等表)高达数亿记录,这不得不让我们考虑做HMS的federation方案,另外,Mysql的稳定性也提出了更高的要求。本文正是在Mysql交由更专业的DBA团队运维的背景下产生的。

在Hive版本升级中, 需要考虑的是版本间的语法兼容性, 这应该是升级中最大的困难。
而元数据Hive MetaStore(HMS)的升级相对而言就简单很多,本文主要关注HMS的升级。

本文适用于想进行Hive元数据升级,尤其是想对Hive元数据Mysql做迁移改造的同学借鉴,也适于对Hive源码感兴趣的同学参考。

2 HiveSchemaTool源码分析

如果你亲手搭建过Hive,想必肯定对命令schematool -dbType mysql -initSchema有印象,因为在搭建完Hive之后,执行该命令后,你会惊奇地发现Mysql中会创建好相应的元数据表信息。schematool主要完成元数据库中表结构(如DBS,TBLS等)的更新创建。那它的背后是如何完成的呢?

2.1 schematool 的用法

你应该善于使用help:

schematool -help
usage: schemaTool
 -dbOpts <databaseOpts>             Backend DB specific options
 -dbType <databaseType>             Metastore database type
 -dryRun                            list SQL scripts (no execute)
 -help                              print this message
 -info                              Show config and schema details
 -initSchema                        Schema initialization
 -initSchemaTo <initTo>             Schema initialization to a version
 -passWord <password>               Override config file password
 -upgradeSchema                     Schema upgrade
 -upgradeSchemaFrom <upgradeFrom>   Schema upgrade from a version
 -userName <user>                   Override config file user name
 -verbose                           only print SQL statements

dryRun是升级演习模式。可以打印出将要执行的SQL脚本信息。从而提醒我们该去哪个文件查看此次变更内容,让我们更清楚将要发生什么;
verbose参数可以打印出每个执行的SQL内容。 方便在失败时,我们知道是哪个环节出现了问题。

其他选项比较简单,不再一一介绍。

2.2 schematool 的功能

schematool主要有如下功能:

  • 元数据版本升级
  • 元数据初始化
  • 元数据信息查看

2.3 核心代码分析

2.3.1 main入口函数

  • 第一步参数解析

  • 第二步参数校验

  • 第三步强制开启版本校验

  • 第四步参数赋值

  • 第五步开始版本升级/初始化

源码流程比较清晰,不再多叙,可参考源码自行阅读。

2.3.2 upgrade

关于版本升级主要有两种方式: 不指定版本号和指定版本号

  • 1 不指定版本号升级
    upgradeSchema: schematool -upgradeSchema
    默认不指定版本号升级, 这时是从mysql中读取版本号.

  • 2 指定版本号升级
    upgradeSchemaFrom: schematool -upgradeSchemaFrom <upgradeFrom>
    指定版本号升级,我们可以指定升级的版本号.这里可以是我们内部版本号
    (如果是内部版本,可以使用指定内部版本号实现升级)

不管是否指定版本号升级, 最终都会调用方法:
org.apache.hive.beeline.HiveSchemaTool#doUpgrade(java.lang.String)

doUpgrade分析

1 等价版本号

合法的可识别的版本号保存在两个地方:

一是在硬代码静态变量中定义好的:
org.apache.hadoop.hive.metastore.MetaStoreSchemaInfo#EQUIVALENT_VERSIONS
这里定义的意思是说有些版本号之间的schema的变化是一致的,升级是等价的.

  // 这里注明了一些等价的版本,也就是元数据没有变化的版本,如 1.2.1 和 1.2.0 版本的元数据是一致的。
  private static final Map<String, String> EQUIVALENT_VERSIONS =
      ImmutableMap.of("0.13.1", "0.13.0",
          "1.0.0", "0.14.0",
          "1.0.1", "1.0.0",
          "1.1.1", "1.1.0",
          "1.2.1", "1.2.0"
      );

二是从数据库中获取版本号(这里是从VERSION表中读取版本号).

2 升级脚本注册文件

命名规则:upgrade.order.<dbType>

以mysql库为例:
upgrade.order.mysql:该文件中定义了mysql升级将要执行的脚本名标识。

# upgrade.order.mysql 文件内容:
0.5.0-to-0.6.0
0.6.0-to-0.7.0
0.7.0-to-0.8.0
0.8.0-to-0.9.0
0.9.0-to-0.10.0
0.10.0-to-0.11.0
0.11.0-to-0.12.0
0.12.0-to-0.13.0
0.13.0-to-0.14.0
0.14.0-to-1.1.0
1.1.0-to-1.2.0

upgrade.order.mysql文件中定义了升级脚本名标识,该标识以升级的当前版本号为前缀。这里也规定了升级的版本之间的依赖关系。如0.6.0版本,无法跨版本升级至1.2.0,只能通过逐级升级至1.2.0。

如何跨版本升级?
没错,聪明的你肯定想到了:我们可以通过修改该文件来实现跨元数据的版本升级。

如何自定义内部版本升级?
这里如果我们自定义内部版本升级, 我们可以在该文件中增加想要升级的版本标识,如:
1.2.1-to-1.2.1-stefan_r,假定是mysql库,我们需要在scripts/upgrade/mysql目录下,定义内部版本升级脚本文件:
upgrage-1.2.1-to-1.2.1-stefan_r.mysql.sql

为什么是这个文件名呢?下面我们看升级脚本文件命名规则。

3 升级脚本文件命名规则

upgrage-<upgrade.order.mysql中定义的文件标识>.<dbType>.sql

image.png
4 升级脚本文件的获取

获取升级脚本文件的方法是:
org.apache.hadoop.hive.metastore.MetaStoreSchemaInfo#getUpgradeScripts

比如我们当前版本是1.1.0, 那执行如下命令
schematool -dbType mysql -initSchemaTo 1.1.0
, 那么会根据指定的版本号1.1.0 在upgrade.order.mysql 中找该版本号前缀的标识,将会升级到1.2.0版本(1.1.0-to-1.2.0)

当然,如果我们执行如下命令
schematool -dbType mysql -initSchema
该升级哪个版本呢?
此时的版本号是取<hive.version.shortname>1.2.0</hive.version.shortname>, 这里不多展开。

5 升级脚本的执行

这里是利用beeline通过JDBC连接对应的数据库,完成升级脚本的执行。

这里有几个模式:
演习模式: 可以通过指定 -dryRun 开启。该模式不会真正地升级,会打印升级的文件。
verbose模式: 可以通过 -verbose 开启。该模式会将升级中执行的SQL打印出来。

通常不同issue对应的升级脚本都是有序独立提供,

image.png

主升级脚本中通常source他们,来看看 upgrade-0.14.0-to-1.1.0.mysql.sql 升级脚本的内容:

SELECT 'Upgrading MetaStore schema from 0.14.0 to 1.1.0' AS ' ';

SOURCE 020-HIVE-9296.mysql.sql;

UPDATE VERSION SET SCHEMA_VERSION='1.1.0', VERSION_COMMENT='Hive release version 1.1.0' where VER_ID=1;
SELECT 'Finished upgrading MetaStore schema from 0.14.0 to 1.1.0' AS ' ';


以上是升级upgrade中的一些细节,理解了升级,下面的初始化init理解起来就容易地多了。

2.3.2 init

初始化同样有两种方式: 不指定版本号和指定版本号

  • 1 不指定版本号升级
    initSchema: schematool -dbType -initSchema
    默认不指定版本号升级, 这时是从mysql中读取版本号.

  • 2 指定版本号升级
    initSchemaTo: schematool -dbType -initSchemaTo <initVersion>

不管是否指定版本号升级, 最终都会调用方法:
org.apache.hive.beeline.HiveSchemaTool#doInit(java.lang.String)

doInit分析

1 初始化脚本文件命名规则

hive-schema-<toVersion>.<dbType>.sql

image.png

2 升级脚本文件的获取

这个比较简单,根据初始化的目标版本号,获取。

其他都与upgrade类似。

3 元数据升级的一些注意事项

如果是不停服的升级,这里有两点需要注意:

一是要关闭版本严格校验模式。
如果在不停服的升级过程中可以做到对用户透明,避免客户端请求失败。

    METASTORE_SCHEMA_VERIFICATION("hive.metastore.schema.verification", false,
        "Enforce metastore schema version consistency.\n" +
        "True: Verify that version information stored in metastore matches with one from Hive jars.  Also disable automatic\n" +
        "      schema migration attempt. Users are required to manually migrate schema after Hive upgrade which ensures\n" +
        "      proper metastore schema migration. (Default)\n" +
        "False: Warn if the version information stored in metastore doesn't match with one from in Hive jars."),

二是要关闭JDO框架自动更新元数据的功能(生产环境,不建议打开)。
因为元数据的更新由我们手工操作完成,这样更可控,我们更清楚发生了什么。如果打开该开关,JDO框架会默认创建缺失的表等。

    METASTORE_AUTO_CREATE_ALL("datanucleus.schema.autoCreateAll", false,
        "creates necessary schema on a startup if one doesn't exist. set this to false, after creating it once"),

最后别忘了在升级完成后,打开版本严格校验模式(当然也可以选择关闭)。

为什么我初始化之后default库没有自动创建?

有时候在initSchema之后,发现default库并没有创建,这是因为没有打开开关:

    METASTORE_DEFAULT_DBROLES_INIT("hive.metastore.default.dbroles.init", false,
        "If true, default db/roles are created and admin roles are added every time when metastore server starts"),

Thanks

54686973 20617274 69636C65 20697320 64656469 63617465 6420746F 20526F6E 67657220 77686F20 49206465 65706C79 206C6F76 65642E54 68697320 61727469 636C6520 69732064 65646963 61746564 20746F20 526F6E67 65722077 686F2049 20646565 706C7920 6C6F7665 642E5468 69732061 72746963 6C652069 73206465 64696361 74656420 746F2052 6F6E6765 72207768 6F204920 64656570 6C79206C 6F766564 2E

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,802评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,109评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,683评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,458评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,452评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,505评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,901评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,550评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,763评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,556评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,629评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,330评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,898评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,897评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,140评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,807评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,339评论 2 342

推荐阅读更多精彩内容

  • Hive是什么 我们知道传统数据存储都是存储在关系型数据库中,它们使用一种SQL(结构化查询语言)方言来查询数据库...
    零度沸腾_yjz阅读 1,099评论 0 7
  • Zookeeper用于集群主备切换。 YARN让集群具备更好的扩展性。 Spark没有存储能力。 Spark的Ma...
    Yobhel阅读 7,232评论 0 34
  • 本文是对Hive组件的学习的一个初步总结,包括如下章节的内容: Hive是什么 Hive安装 快速上手 Hive元...
    我是老薛阅读 1,905评论 1 23
  • hive.ddl.output.format:hive的ddl语句的输出格式,默认是text,纯文本,还有json...
    博弈史密斯阅读 1,931评论 0 6
  • 不知道从哪一天起,我开始厌倦了上班。也不是上班不好,也不是和同事相处的不好,而是对以后的担忧,和对大环境的...
    追逐梦的自由阅读 137评论 0 0