1 背景
隨著公司業(yè)務(wù)的井噴式發(fā)展,數(shù)倉元數(shù)據(jù)也日益龐大恕刘,尤其是存在很多設(shè)計不合理的大分區(qū)表市殷,導(dǎo)致一些元數(shù)據(jù)表(如PARTITIONS,PARTITION_PARAMS等表)高達(dá)數(shù)億記錄勘畔,這不得不讓我們考慮做HMS的federation方案,另外丽惶,Mysql的穩(wěn)定性也提出了更高的要求炫七。本文正是在Mysql交由更專業(yè)的DBA團隊運維的背景下產(chǎn)生的。
在Hive版本升級中, 需要考慮的是版本間的語法兼容性, 這應(yīng)該是升級中最大的困難钾唬。
而元數(shù)據(jù)Hive MetaStore(HMS)的升級相對而言就簡單很多万哪,本文主要關(guān)注HMS的升級侠驯。
本文適用于想進行Hive元數(shù)據(jù)升級,尤其是想對Hive元數(shù)據(jù)Mysql做遷移改造的同學(xué)借鑒奕巍,也適于對Hive源碼感興趣的同學(xué)參考吟策。
2 HiveSchemaTool源碼分析
如果你親手搭建過Hive,想必肯定對命令schematool -dbType mysql -initSchema
有印象的止,因為在搭建完Hive之后檩坚,執(zhí)行該命令后,你會驚奇地發(fā)現(xiàn)Mysql中會創(chuàng)建好相應(yīng)的元數(shù)據(jù)表信息冲杀。schematool
主要完成元數(shù)據(jù)庫中表結(jié)構(gòu)(如DBS效床,TBLS等)的更新創(chuàng)建睹酌。那它的背后是如何完成的呢权谁?
2.1 schematool 的用法
你應(yīng)該善于使用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是升級演習(xí)模式。可以打印出將要執(zhí)行的SQL腳本信息憋沿。從而提醒我們該去哪個文件查看此次變更內(nèi)容旺芽,讓我們更清楚將要發(fā)生什么;
verbose參數(shù)可以打印出每個執(zhí)行的SQL內(nèi)容辐啄。 方便在失敗時采章,我們知道是哪個環(huán)節(jié)出現(xiàn)了問題。
其他選項比較簡單壶辜,不再一一介紹悯舟。
2.2 schematool 的功能
schematool主要有如下功能:
- 元數(shù)據(jù)版本升級
- 元數(shù)據(jù)初始化
- 元數(shù)據(jù)信息查看
2.3 核心代碼分析
2.3.1 main入口函數(shù)
第一步參數(shù)解析
第二步參數(shù)校驗
第三步強制開啟版本校驗
第四步參數(shù)賦值
第五步開始版本升級/初始化
源碼流程比較清晰,不再多敘砸民,可參考源碼自行閱讀抵怎。
2.3.2 upgrade
關(guān)于版本升級主要有兩種方式: 不指定版本號和指定版本號
1 不指定版本號升級
upgradeSchema: schematool -upgradeSchema
默認(rèn)不指定版本號升級, 這時是從mysql中讀取版本號.2 指定版本號升級
upgradeSchemaFrom: schematool -upgradeSchemaFrom <upgradeFrom>
指定版本號升級,我們可以指定升級的版本號.這里可以是我們內(nèi)部版本號
(如果是內(nèi)部版本,可以使用指定內(nèi)部版本號實現(xiàn)升級)
不管是否指定版本號升級, 最終都會調(diào)用方法:
org.apache.hive.beeline.HiveSchemaTool#doUpgrade(java.lang.String)
doUpgrade分析
1 等價版本號
合法的可識別的版本號保存在兩個地方:
一是在硬代碼靜態(tài)變量中定義好的:
org.apache.hadoop.hive.metastore.MetaStoreSchemaInfo#EQUIVALENT_VERSIONS
這里定義的意思是說有些版本號之間的schema的變化是一致的,升級是等價的.
// 這里注明了一些等價的版本岭参,也就是元數(shù)據(jù)沒有變化的版本反惕,如 1.2.1 和 1.2.0 版本的元數(shù)據(jù)是一致的。
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"
);
二是從數(shù)據(jù)庫中獲取版本號(這里是從VERSION表中讀取版本號).
2 升級腳本注冊文件
命名規(guī)則:upgrade.order.<dbType>
以mysql庫為例:
upgrade.order.mysql:該文件中定義了mysql升級將要執(zhí)行的腳本名標(biāo)識演侯。
# upgrade.order.mysql 文件內(nèi)容:
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文件中定義了升級腳本名標(biāo)識姿染,該標(biāo)識以升級的當(dāng)前版本號為前綴。這里也規(guī)定了升級的版本之間的依賴關(guān)系秒际。如0.6.0版本悬赏,無法跨版本升級至1.2.0,只能通過逐級升級至1.2.0娄徊。
如何跨版本升級赢笨?
沒錯,聰明的你肯定想到了:我們可以通過修改該文件來實現(xiàn)跨元數(shù)據(jù)的版本升級仇冯。
如何自定義內(nèi)部版本升級筛谚?
這里如果我們自定義內(nèi)部版本升級, 我們可以在該文件中增加想要升級的版本標(biāo)識,如:
1.2.1-to-1.2.1-stefan_r
中鼠,假定是mysql庫可婶,我們需要在scripts/upgrade/mysql目錄下,定義內(nèi)部版本升級腳本文件:
upgrage-1.2.1-to-1.2.1-stefan_r.mysql.sql
為什么是這個文件名呢援雇?下面我們看升級腳本文件命名規(guī)則矛渴。
3 升級腳本文件命名規(guī)則
upgrage-<upgrade.order.mysql中定義的文件標(biāo)識>.<dbType>.sql
4 升級腳本文件的獲取
獲取升級腳本文件的方法是:
org.apache.hadoop.hive.metastore.MetaStoreSchemaInfo#getUpgradeScripts
比如我們當(dāng)前版本是1.1.0, 那執(zhí)行如下命令
schematool -dbType mysql -initSchemaTo 1.1.0
, 那么會根據(jù)指定的版本號1.1.0 在upgrade.order.mysql 中找該版本號前綴的標(biāo)識惫搏,將會升級到1.2.0版本(1.1.0-to-1.2.0)
當(dāng)然具温,如果我們執(zhí)行如下命令
schematool -dbType mysql -initSchema
該升級哪個版本呢?
此時的版本號是取<hive.version.shortname>1.2.0</hive.version.shortname>
, 這里不多展開筐赔。
5 升級腳本的執(zhí)行
這里是利用beeline通過JDBC連接對應(yīng)的數(shù)據(jù)庫铣猩,完成升級腳本的執(zhí)行。
這里有幾個模式:
演習(xí)模式: 可以通過指定 -dryRun
開啟茴丰。該模式不會真正地升級达皿,會打印升級的文件。
verbose模式: 可以通過 -verbose
開啟贿肩。該模式會將升級中執(zhí)行的SQL打印出來峦椰。
通常不同issue對應(yīng)的升級腳本都是有序獨立提供,
主升級腳本中通常source他們汰规,來看看 upgrade-0.14.0-to-1.1.0.mysql.sql 升級腳本的內(nèi)容:
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中的一些細(xì)節(jié)汤功,理解了升級,下面的初始化init理解起來就容易地多了溜哮。
2.3.2 init
初始化同樣有兩種方式: 不指定版本號和指定版本號
1 不指定版本號升級
initSchema: schematool -dbType -initSchema
默認(rèn)不指定版本號升級, 這時是從mysql中讀取版本號.2 指定版本號升級
initSchemaTo: schematool -dbType -initSchemaTo <initVersion>
不管是否指定版本號升級, 最終都會調(diào)用方法:
org.apache.hive.beeline.HiveSchemaTool#doInit(java.lang.String)
doInit分析
1 初始化腳本文件命名規(guī)則
hive-schema-<toVersion>.<dbType>.sql
2 升級腳本文件的獲取
這個比較簡單滔金,根據(jù)初始化的目標(biāo)版本號,獲取茬射。
其他都與upgrade類似鹦蠕。
3 元數(shù)據(jù)升級的一些注意事項
如果是不停服的升級,這里有兩點需要注意:
一是要關(guān)閉版本嚴(yán)格校驗?zāi)J健?/strong>
如果在不停服的升級過程中可以做到對用戶透明在抛,避免客戶端請求失敗钟病。
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."),
二是要關(guān)閉JDO框架自動更新元數(shù)據(jù)的功能(生產(chǎn)環(huán)境,不建議打開)刚梭。
因為元數(shù)據(jù)的更新由我們手工操作完成肠阱,這樣更可控,我們更清楚發(fā)生了什么朴读。如果打開該開關(guān)屹徘,JDO框架會默認(rèn)創(chuàng)建缺失的表等。
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"),
最后別忘了在升級完成后衅金,打開版本嚴(yán)格校驗?zāi)J剑ó?dāng)然也可以選擇關(guān)閉)噪伊。
為什么我初始化之后default庫沒有自動創(chuàng)建簿煌?
有時候在initSchema之后,發(fā)現(xiàn)default庫并沒有創(chuàng)建鉴吹,這是因為沒有打開開關(guān):
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