异常重现
在Hive中创建了一个分桶事务表TEST_TRANSACTIONAL,表结构如下:
CREATE TABLE IF NOT EXISTS TEST_TRANSACTIONAL
(
APPLY_NO STRING
,APPLYNO STRING
,NAME STRING
)
Clustered By(APPLY_NO) Into 23 Buckets
Stored As Orc
TblProperties('transactional' = 'true');
然后使用create table TEST_NOT_TRANSACTIONAL like TEST_TRANSACTIONAL的建表方式创建了另一张表,向表TEST_NOT_TRANSACTIONAL插入了四次数据,一共四条数据,之后使用语句insert into TEST_TRANSACTIONAL select * from TEST_NOT_TRANSACTIONAL将数据插入到分桶事务表中,最后对分桶事务表进行查询,发现结果并不是四条数据,而是只有一条数据。
异常分析
查询异常的表是分桶事务表,在完成insert into操作之后,还需要对表进行一次合并的操作,这个操作会在后台异步的启动一个MR任务对数据进行合并,如果没有合并,查询只会显示第一条数据。
解决方法
1.在CM上修改配置
修改HiveServer2的高级配置代码段
<property>
<name>hive.support.concurrency</name>
<value>true</value>
</property>
<property>
<name>hive.enforce.bucketing</name>
<value>true</value>
</property>
<property>
<name>hive.exec.dynamic.partition.mode</name>
<value>nonstrict</value>
</property>
<property>
<name>hive.txn.manager</name>
<value>org.apache.hadoop.hive.ql.lockmgr.DbTxnManager</value>
</property>
修改HiveMetastore的高级代码段配置
<property>
<name>hive.compactor.initiator.on</name>
<value>true</value>
</property>
<property>
<name>hive.compactor.worker.threads</name>
<value>1</value>
</property>
2.在Hive中新建一个分桶事务表
CREATE TABLE IF NOT EXISTS TEST_DATA.TEST_TRANSACTIONAL
(
APPLY_NO STRING Comment '小贷贷款标的号(平安传过来的)'
,APPLYNO STRING Comment '行内贷款标的号'
,NAME STRING Comment '客户名称'
)
Comment '安e贷申请'
Clustered By(APPLY_NO) Into 23 Buckets
Stored As Orc
TblProperties('transactional' = 'true');
3.使用like的方式建立另外一张表
create table TEST_DATA.TEST_NOT_TRANSACTIONAL like TEST_DATA.TEST_TRANSACTIONAL;
4.向非事务表中多次插入数据
insert into TEST_DATA.TEST_NOT_TRANSACTIONAL values ('ylb2017112718053546154234','22201902181000000043','skyon');
insert into TEST_DATA.TEST_NOT_TRANSACTIONAL values ('ylb2017120111035124273550','22201311011000000051','skyon2');
insert into TEST_DATA.TEST_NOT_TRANSACTIONAL values ('ylb2017120416494266807634','22201803011000000077','skyon3');
insert into TEST_DATA.TEST_NOT_TRANSACTIONAL values ('ylb2017112718054244710450','22201310011000000050','skyon4');
5.将非事务表的数据插入到事务表
insert into TEST_DATA.TEST_TRANSACTIONAL select * from TEST_DATA.TEST_NOT_TRANSACTIONAL;
6.让事务表完成数据合并的操作
ALTER TABLE TEST_DATA.TEST_TRANSACTIONAL COMPACT 'MAJOR';
7.上一步合并操作会异步的执行一个MR任务,等待MR任务执行完成,在Yarn上查看
8.在合并的MR任务完成后,查询事务表的数据
事务表的数据查询正常,一共四条数据。
总结
1.在对事务表进行insert操作后,需要进行合并操作,否则查询数据会出现问题。
2.Hive的Compaction操作分为两种,Minor和Major,Minor会将所有的delta文件压缩
为一个文件,delete文件也压缩为一个。压缩过程是在Hive Metastore中进行的;Major会将所有文件合并为一个文件,以base_N的形式命名,其中N表示最新的写事务ID。
3.在CM中设置Hive事务相关的参数时要注意,为不同的角色Hive Server2和Hive Metastore分别设置的参数,Hive Server2中设置的参数,hive.support.concurrency设置为true,开启并发;hive.enforce.bucketing设置为true,开启强制分桶,因为在Hive中事务表必须分桶;hive.exec.dynamic.partition.mode设置为nonstrict,因为在一个事务中,可能不止会更新一个Partition,而且更新时无法控制道理哪些Partition会被操作,因此为了支持事务,此参数需这样设置;hive.txn.manager参数指定Hive事务管理器。Hive Metastore中设置的参数,hive.compactor.initiator.on设置为true,此参数设置为true,会在Metastore实例上运行Initiator和cleaner,Initiator进程会发现表和分区中需要进行合并的数据文件,cleaner负责删除合并后已经不再需要的文件;hive.compactor.worker.threads设置为1,在合并时,一个Worker处理一个合并任务,一个合并任务也就是一个MR任务,此参数的值确定每个Metastore中Worker的个数。
Fayson的github: https://github.com/fayson/cdhproject