[hive-3.1]Hive 事务和锁

使用 DbLockManager 时,当 insert into 表的一个分区时,select 其他分区卡住。使用 ZookeeperHiveLockManager 时不会。DbLockManager 和 ZookeeperHiveLockManager 的实现有差异 。

1. 使用 hive-cli 执行以下语句

create table t1(c1 string) stored as textfile;
load data local inpath '/etc/profile' overwrite into table t1;

create table t2(c1 int) partitioned by (pt string);

insert overwrite table t2 partition (pt=1) select length(c1) from t1;

在一个会话 session 1 执行时:

insert overwrite table t2 partition (pt=2) select length(c1) from t1;

在会话 session 1 的语句执行时, 另一个会话 session 2 中执行:


select * from t2 where pt=1;

会发现 session 2 在 session 1 执行结束后才开始执行。

2. 原因分析

当前配置:

   <property>
      <name>hive.txn.manager</name>
      <value>org.apache.hadoop.hive.ql.lockmgr.DbTxnManager</value>
    </property>

在 session 1 执行时,会获取 t2 表 partition (pt=2) 这个分区的 exclusive write 权限,现在没有其他会话操作表 t2,获取锁。
session 2的语句,会获取 t2 表的两个权限,分别是 t2 表的 shared read 权限和 t2 表 partition(pt=1) 的 shared read 权限这两个权限。
原因 t2 表的 shared read 权限获取不了。

3. 解决方案

3.1 insert overwrite 的解决方案

hive-site.xml 修改以下参数的值

   <property>
      <name>hive.txn.manager</name>
      <value>org.apache.hadoop.hive.ql.lockmgr.DummyTxnManager</value>
    </property>
    <property>
      <name>hive.support.concurrency</name>
      <value>false</value>
  </property>

以上配置,当调用获取锁、释放锁、开启事务、关闭事务等调用时直接返回,不论 hive.lock.manager 设置为何值。

3.2 insert overwrite 的解决方案2

hive-site.xml 修改以下参数的值。以下配置,没有事务功能,仅有锁的功能,锁使用 Zookeeper 实现。

   <property>
      <name>hive.txn.manager</name>
      <value>org.apache.hadoop.hive.ql.lockmgr.DummyTxnManager</value>
    </property>
    <property>
      <name>hive.support.concurrency</name>
      <value>true</value>
  </property>
    <property>
      <name>hive.lock.manager</name>
      <value>org.apache.hadoop.hive.ql.lockmgr.zookeeper.ZooKeeperHiveLockManager</value>
  </property>

3.3 insert into 的解决方案

如果是 insert into 而不是insert overwrite 时,可以设置 hive.txn.strict.locking.mode=false 解决,这时 insert into 获取共享锁。
各配置项如下:

   <property>
      <name>hive.txn.manager</name>
      <value>org.apache.hadoop.hive.ql.lockmgr.DbTxnManager</value>
    </property>
    <property>
      <name>hive.txn.strict.locking.mode</name>
      <value>false</value>
  </property>

4 机制说明

4.1 总体说明

txn manager 里实例化一个 lock mamanger。

Hive txn manager 一共两种实现,一种是 DbTxnManager,一种是 DummyTxnManager.

4.2 DbTxnManager

如果需要实现事务功能(可以执行 updage,merge 和 delete 操作),Hive 3.1 必须设置为 DbTxnManager。
hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager 时,固定使用 DbLockManager,不论hive.lock.manager 配置为何值。

hive.txn.strict.locking.mode 的作用。仅当 hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager 并且是内部表生效。当值为 false 时,insert into ${TABLE_NAME} partition(不是 insert overwrite table ${TABLE_NAME} partition) 获取 shared 锁。当值为 true 时,insert into ${TABLE_NAME} partition 获取 exclusive 锁。

往分区写数据时,插入一条记录,内容如下:

HL_LOCK_EXT_ID: 2234 // 锁外部 ID
HL_LOCK_INT_ID: 2 // 一个递增编号,和 HL_LOCK_EXT_ID 组成联合主键
HL_TXNID: 2721 // 事务ID 
HL_DB: default // 数据库名
HL_TABLE: t2 // 表名
HL_PARTITION: pt=3 // 分区名
HL_LOCK_STATE: a // 锁状态:a(acquired),w (waiting)
HL_LOCK_TYPE: e // 锁类型: e(exclusive), r (shared), w(LOCK_SEMI_SHARED)
HL_LAST_HEARTBEAT: 0
HL_ACQUIRED_AT: 1658285505000
HL_USER: houzhizhen
HL_HOST: localhost
HL_HEARTBEAT_COUNT: NULL
HL_AGENT_INFO: houzhizhen_20220720105145_3c787b27-94d0-44d1-be62-10965ac3258e
HL_BLOCKEDBY_EXT_ID: NULL
HL_BLOCKEDBY_INT_ID: NULL

当读取一个分区时(pt=1),需要两个权限,一个是 表的 shared 权限,一个是分区的 shared 权限。表的权限拿不到,因为按数据库名和表名拿到的 lock 记录时exclusive。

HL_LOCK_EXT_ID: 2235
HL_LOCK_INT_ID: 1
HL_TXNID: 2722
HL_DB: default
HL_TABLE: t2
HL_PARTITION: NULL
HL_LOCK_STATE: w
HL_LOCK_TYPE: r
HL_LAST_HEARTBEAT: 0
HL_ACQUIRED_AT: NULL
HL_USER: houzhizhen
HL_HOST: localhost
HL_HEARTBEAT_COUNT: NULL
HL_AGENT_INFO: houzhizhen_20220720105214_f33da326-e509-47af-a208-ea1a7b6b9783
HL_BLOCKEDBY_EXT_ID: NULL
HL_BLOCKEDBY_INT_ID: NULL

4.3 DummyTxnManager

hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DummyTxnManager 并且 hive.support.concurrency=false 的时候,不会实例化一个 lock manager。调用获取锁、释放锁、开启事务、关闭事务等调用时直接返回。

hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DummyTxnManager 并且 hive.support.concurrency=true 时, lock manager 根据 hive.lock.manager 的值创建对应的对象。这时,没有事务的功能。开启事务、关闭事务调用时直接返回。但是获取锁和释放锁操作,转给 lock manager 对应的方法处理。

DummyTxnManager 会把获取的权限的请求进行拆分。
当写分区(pt=3) 时,锁对象(db=default, table=t2, pt=3),拆成以下3个锁对象。

dbLock = (pathName=["default"], type="shared");
tableLock = (pathName=["default", "t2"], type="shared");
partitionLock = (pathName=["default", "t2", "pt=3"], type="exclusive");

当使用 ZookeeperHiveLockManager 时,把这些锁对象的 pathName 转成 zookeeper 的 znode,申请之后的 znode 为:

[zk: localhost:2181(CONNECTED) 6] ls /hive_zookeeper_namespace/default
[LOCK-SHARED-0000000000, t2]
[zk: localhost:2181(CONNECTED) 10] ls /hive_zookeeper_namespace/default/t2
[LOCK-SHARED-0000000000, pt=3]
[zk: localhost:2181(CONNECTED) 11] ls /hive_zookeeper_namespace/default/t2/pt=3
[LOCK-EXCLUSIVE-0000000000]

当读分区(pt=1) 时,需要两个锁对象(db=default, table=t2, pt=1)和(db=default, table=t2)。

(db=default, table=t2, pt=1)拆成以下3个锁对象。

dbLock = (pathName=["default"], type="shared");
tableLock = (pathName=["default", "t2"], type="shared");
partitionLock = (pathName=["default", "t2", "pt=1"], type="shared");

(db=default, table=t2)拆成以下2个锁对象。

dbLock = (pathName=["default"], type="shared");
tableLock = (pathName=["default", "t2"], type="shared");

对这5个对象进行去重。
得到3个对象

dbLock = (pathName=["default"], type="shared");
tableLock = (pathName=["default", "t2"], type="shared");
partitionLock = (pathName=["default", "t2", "pt=1"], type="shared");

把这些锁对象的 pathName 转成 zookeeper 的 znode,申请之后的 znode 为:

[zk: localhost:2181(CONNECTED) 6] ls /hive_zookeeper_namespace/default
[LOCK-SHARED-0000000000, t2]
[zk: localhost:2181(CONNECTED) 10] ls /hive_zookeeper_namespace/default/t2
[LOCK-SHARED-0000000000, pt=3]
[zk: localhost:2181(CONNECTED) 11] ls /hive_zookeeper_namespace/default/t2/pt=1
[LOCK-SHARED-0000000000]

所以当写 pt=3 时,读取 pt=1 是没有问题。

### HiveSQL 安装教程与环境配置 #### 3.1 准备工作 为了成功安装配置HiveSQL,需先准备好必要的软件包支持工具。这包括但不限于Java开发套件(JDK),Apache Hadoop集群以及MySQL用于元数据存储。 #### 3.2 下载并解压Hive 从官方网站下载适合版本的Hive压缩文件至服务器上,并将其解压缩到指定目录下。通常建议放置于`/usr/local/`路径之下以便管理维护[^1]。 #### 3.3 配置环境变量 编辑系统的`.bashrc`或相应的shell初始化脚本,添加如下两行来设置HIVE_HOME环境变量及PATH路径: ```bash export HIVE_HOME=/path/to/hive export PATH=$PATH:$HIVE_HOME/bin ``` 完成上述更改之后记得执行source命令使新的环境变量生效: ```bash source ~/.bashrc ``` #### 3.4 初始化Metastore数据库模式 进入Hive二进制文件夹内的bin子目录,通过`schematool`工具初始化MySQL中的metastore schema结构: ```bash cd /usr/lib/hive/bin ./schematool --dbType mysql --initSchema ``` 此操作会依据所选关系型数据库管理系统(RDBMS)类型自动建立所需的表格架构。 #### 3.5 修改核心站点配置文件core-site.xml 针对HDFS上的默认保存位置做出相应调整,在`$HADOOP_HOME/etc/hadoop/core-site.xml`中加入以下属性定义以指向实际使用的分布式文件系统地址: ```xml <property> <name>fs.defaultFS</name> <value>hdfs://namenode:8020</value> </property> ``` 此处应替换为具体环境中NameNode主机名及其端口号组合而成的有效URL字符串。 #### 3.6 调整hive-site.xml参数设定 同样地,在位于`${HIVE_HOME}/conf/`下的hive-site.xml文档里补充必要的连接选项,比如JDBC URL、用户名密码等信息用来关联外部RDBMS实例作为内部metadata repository之用;同时还可以考虑开启ACID特性支持从而增强事务处理能力[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值