IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Hive未关闭表的事务功能(ACID)所引发的一系列Bug问题 -> 正文阅读

[大数据]Hive未关闭表的事务功能(ACID)所引发的一系列Bug问题

Hive 未关闭表的事务功能(ACID)的问题

一、Hive 未关闭表的事务功能(ACID)的所引发的问题

记录一次HDP3.0 的hive 3.1.2由于未关闭ACID功能,导致使用到用户画像的Spark计算引擎报错,无法处理数据,impala无法查询的问题。由于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 。

hive3默认开启ACID功能引起的spark和impala报错的问题

在hdp3.1.5中hive3中内部表默认开启了ACID,当spark和impala创建和读取内部表的时候会报错,网上建议的方式是舍弃掉acid特性。

hive.strict.managed.tables=false 
hive.create.as.insert.only=false 
metastore.create.as.acid=false

对应hdp的hive默认配置做如下修改,重启hive服务后确实可以生效:

在这里插入图片描述

什么是事务表

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

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

  • 支持原子性update操作的Hive表称为事务表。
  • 事务表和普通内部表的区别:
    在这里插入图片描述
    可以看到,事务表分为两种,一种是ORC格式,能完整的支持CRUD操作(增删改查),一种是普通的TextFile文件格式,只符合Insert-only特性.

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

表类型ACID文件格式插入更新/删除
托管表:CRUD事务ORC
托管表:仅插入式事务任意格式没有
托管表:临时没有任意格式没有
外部表没有任意格式没有

其中托管表是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表并不建议使用事务表。因为事务表的限制很多,加上由于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 |
+----------------------------------------------------+

问题解决办法

那么如果项目一开始就没有关闭hive的ACID设置,怎么解决这个问题呢?

思路:先关闭ACID设置

  • 使用shell脚本或者java程序连接jdbc,导出已有库的所有表的建表语句,

    只保留create table 原表名_bak(
    
    col1 type,
    
    col2 type,
    
    ...
    
    )partition by (分区字段)
    
    store as ORC;
    
  • 执行建表语句,新建表名,然后将数据从老表中查询出来,覆写到新表中。

  • 然后旧表更名为 table名_old,新表面更名为原表名,这样就不影响到下游的使用。

  • 更名操作命令:

  • 当前Hive版本:3.1.3000.7.1.7.0-551
    创建hive外部表: CREATE TABLE IF NOT EXISTS `alter_test` (a string,b string) STORED AS ORC TBLPROPERTIES("transactional"="false");
    转hive内部表:ALTER TABLE alter_test SET TBLPROPERTIES('external'='false');
    重命名:ALTER TABLE alter_test RENAME TO alter_test_bak;
    
  • 设置hive表的Location的hdfs路径:

  • ALTER TABLE <tableName> RENAME TO <newTableName>;
    ALTER TABLE <newTableName> set location "hdfs://<location>";
    
  • 如果在编写shell脚本时候导出的建表语句有格式化输出可以使用beeline如下命令:

  • 在这里插入图片描述
    如果创建的表impala还是无法查询到数据,记得可能是impala的元数据没有及时更新。可执行如下命令刷新元数据:

  • invalidate metadata 全量刷新,性能消耗较大,主要用于 hive 当中新建数据库或者数据库表的时候来进行刷新。

  • refresh dbname.tablename 增量刷新,刷新某一张表的元数据,主要用于刷新 hive 当中数据表里面的数据改变的情况。

  • quit/exit 命令 从 Impala shell 中弹出

  • explain 命令 用于查看 sql 语句的执行计划


  • 最佳解决方案
  • 新建一个库与旧的数据库做个区分,比如旧库ODS,新库ODS_new;然后在新库下面把所有表重新建一遍。
  • 下游只需更改数据源的库名就行,表名不变。

二、root 进入hive 报错:Permission denied: user=root, access=WRITE, inode=“/user/root”:hdfs:hdfs:drwxr-xr-x

使用root用户执行hive -f /home/insert.sql报错
在这里插入图片描述
解决办法:

  1. 进入 Ambari,

  2. 进入HDFS,

  3. 点击Configs
    在这里插入图片描述

  4. 打开 Advanced hdfs-site,设置dfs.permissions.enabled=false.

  5. 重启HDFS,以及相关组建。

三、Hive表更名问题——RENAME TABLE

RENAME TABLE

ALTER TABLE table_name RENAME TO new_table_name

这个命令可以让用户为表更名。数据所在的位置和分区名并不改变。换而言之,老的表名并未“释放”,对老表的更改会改变新表的数据?
答案是否定的,数据所在的位置会移动到hive表默认路径下。如果建表是指定路径LOCATION,那么重名之后,路径会变更。


参考博客
Hive ACID和事务表支持详解_u013332124的专栏-CSDN博客
Hive ACID 增删改查 原理以及场景描述_Lara1111的博客-CSDN博客
Hive 官方手册翻译 – Hive Transactions (Hive 事务) - 范振勇 - 博客园 (cnblogs.com)
Spark 无法读取hive 3.x的表数据_u013024563的博客-CSDN博客
Hive表更名问题RENAME TABLE

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-11-05 00:34:29  更:2022-11-05 00:36:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年4日历 -2025/4/23 6:01:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码