Hive 事务表(ACID)问题梳理

问题描述

工作中需要使用pyspark读取Hive中的数据,但是发现可以获取metastore,外部表的数据可以读取,内部表数据有些表报错信息是:

AnalysisException: org.apache.hadoop.hive.ql.metadata.HiveException: Unable to fetch table tb_name. Your client does not appear to support insert-only tables. To skip capability checks, please set metastore.client.capability.check to false. This setting can be set globally, or on the client for the current metastore session. Note that this may lead to incorrect results, data loss, undefined behavior, etc. if your client is actually incompatible. You can also specify custom client capabilities via get_table_req API.

有些表没有报错信息,但是读取数据为空。

初步判断Spark读取Hive的环境配置没有问题,只是Hive表的类型不同导致的。

分析原因

问题原因

HDP3.0 集成了hive 3.0和 spark 2.3,然而spark却读取不了hive表的数据数据,准确来说是内表的数据。

hive 3.0之后默认开启ACID功能,默认建表都是使用ACID的事务表。而spark目前还不支持hive的ACID功能,因此无法读取ACID表的数据。

另外,读取不报错,但是读取不到数据的表INPUTFORMAT=org.apache.hadoop.hive.ql.io.orc.OrcInputFormat

报错insert-only 的表 INPUTFORMAT = org.apache.hadoop.mapred.TextInputFormat

什么是事务表

概念

ACID就是常见数据库事务的四大特性:Atomicity(原子性)、Consistency(一致性)、Isolation(隔离性)、Durability(持久性)。

由于HDFS只支持文件的添加和删除,不支持修改,因此Hive原生并不支持原子性的行级别修改。

支持原子性update操作的Hive表称为事务表。

事务表和普通内部表的区别

在这里插入图片描述

可以看到,事务表分为两种,一种是ORC格式,能完整的支持CRUD操作(增删改查),一种是普通的TextFile文件格式,只符合Insert-only特性.

Hive中支持的表类型和ACID特性如下图所示:

hive的表类型

其中托管表是Hive内部表。

查看表的属性,指令:desc formatted tb_name

非ACID表:

| Table Type:        | MANAGED_TABLE          | NULL  |
| Table Parameters:  | NULL                   | NULL  |
|                    | COLUMN_STATS_ACCURATE  | {\"BASIC_STATS\":\"true\"}  |
|                    | numFiles               | 36554 |
|                    | numPartitions          | 4582  |
|                    | numRows                | 656353471        |
|                    | rawDataSize            | 3687190343914    |
|                    | totalSize              | 191558565757   |
|                    | transient_lastDdlTime  | 1626229162      |

ACID表:

| Table Type:         | MANAGED_TABLE                         | NULL                  |
| Table Parameters:   | NULL                                  | NULL                  |
|                     | bucketing_version                     | 2                     |
|                     | comment                               | 交易日志表             |
|                     | numFiles                              | 2131                  |
|                     | numPartitions                         | 2131                  |
|                     | numRows                               | 1303371497            |
|                     | rawDataSize                           | 0                     |
|                     | totalSize                             | 669842162666          |
|                     | transactional                         | true                  |
|                     | transactional_properties              | insert_only           |
|                     | transient_lastDdlTime                 | 1613705157            |

其中:

  • transactional=true,标识为事务表
  • transactional_properties=insert_only
相关配置

在集群的Hive-site.xml中修改以下参数让新建的表默认不是acid表。

hive.strict.managed.tables=false
hive.create.as.insert.only=false
metastore.create.as.acid=false
事务表的适用场景

对于数仓中的行级数据更新删除需求比较频繁的,可以考虑使用事务表。

但平常的hive表并不建议使用事务表。因为事务表的限制很多,加上由于hive表的特性,也很难满足高并发的场景。

另外,如果事务表太多,并且存在大量的更新操作,metastore后台启动的合并线程会定期的提交MapReduce Job,也会一定程度上增重集群的负担。

结论: 除非有非常迫切的行级更新需求,又只能用hive表来做,才需要去考虑事务表。

注意事项
  1. 不支持 BEGIN、COMMIT、ROLLBACK 等语句,所有的语句都是自动提交
  2. 仅支持ORC格式

设计原理与实现

文件管理格式

HDFS本身是不支持直接修改文件的,也不能保证有人追加内容时的读一致性。

因此,为了支持ACID的特性,Hive只能使用其他数据仓库常用的方法,也就是增量的形式记录更新和删除(也称做读时更新)。

存储在事务表中的数据会被分成两种类型的文件:

  • base文件,用来存放平常的数据
  • delta文件,用来存储新增、更新、删除的数据。每一个事务处理数据的结果都会单独新建一个delta文件夹用来存储数据。

在有用户要读取这个表的数据时,就会将base文件和delta文件都读取到内存,然后进行合并(就是判断哪些记录有被修改,哪些记录被删除等)。

ACID表的文件结构:${Hive_path}/db/table_name/base_{id}/file

Found 2 items                                      |
| -rw-rw----+  3 hdfs hadoop 1091048351 2021-07-13 15:00 /warehouse/tablespace/managed/hive/db_name.db/tb_name/date=2021-06-30/base_0002252/000000_0
| -rw-rw----+  3 hdfs hadoop 1091048351 2021-07-13 15:00 /warehouse/tablespace/managed/hive/db_name.db/tb_name/date=2021-06-30/delta_0000023_0000023_0000/000000_0

其中0000023标识事务ID,0000表示序号,从上面的表中我们可以看到有一个事务的数据还未合并成base。

非ACID表,通过别的表格导入数据,文件目录为:

+----------------------------------------------------+
|                     DFS Output                     |
+----------------------------------------------------+
| 2.6 M  7.9 M  /warehouse/tablespace/managed/hive/db_name.db/tb_name/day=2021-07-18/-ext-10000/000000_0 |
+----------------------------------------------------+

普通内部表文件目录:

+----------------------------------------------------+
|                     DFS Output                     |
+----------------------------------------------------+
| 7.4 M  22.1 M  /warehouse/tablespace/managed/hive/db_name.db/tb_name/day=2021-07-18/000000_0 |
+----------------------------------------------------+
  1. 对于每个写入操作,Hive都会创建一个增量目录,事务管理器将在该目录中写入数据文件;
  2. Hive将所有数据写入由写入ID指定的增量文件,并映射到表示原子操作的事务ID。如果发生故障,该事务将标记为已中止,但它是原子的;
  3. Hive用行ID装饰每一行。

参考博客

  1. Hive ACID和事务表支持详解_u013332124的专栏-CSDN博客
  2. Hive ACID 增删改查 原理以及场景描述_Lara1111的博客-CSDN博客
  3. Hive 官方手册翻译 – Hive Transactions (Hive 事务) - 范振勇 - 博客园 (cnblogs.com)
  4. Spark 无法读取hive 3.x的表数据_u013024563的博客-CSDN博客
  5. Spark Issues Hive ACID
  • 8
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值