hive 锁机制

问题:
1.hive某个sql查询一直被卡住不执行,或偶尔出现执行被 卡住情况(一般出现读写频繁)
2.hive 中某个sql 跑任务偶尔出现申请一点资源,然后一直就停止了申请(出现在此时服务器资源充足,sql 较复杂)

解决方式:
1 排查锁被sql 占用
显示的表级别和分区级别和 EXTENDED 解析那个表占用锁
SHOW LOCKS <TABLE_NAME>;
SHOW LOCKS <TABLE_NAME> EXTENDED;
SHOW LOCKS <TABLE_NAME> PARTITION (<PARTITION_DESC>);
SHOW LOCKS <TABLE_NAME> PARTITION (<PARTITION_DESC>) EXTENDED;

例如: hive 下 show locks dw.dw_user extended

2 如果发现 共享锁和排他锁 作用一张表时 对表进行解锁然后重跑数据

show locks 表名:
可以查看表被锁的情况

解锁 一张表:(区分)
unlock table your_table;

解锁 一张表的分区:
unlock table your_table partition(dt=‘2014-04-01’);

表锁和分区锁是两个不同的锁,对表解锁,对分区是无效的,分区需要单独解锁

注 hive 锁机制
在这里插入图片描述

总结起来就是:

1)查询操作使用共享锁,共享锁是可以多重、并发使用的
2)修改表操作使用独占锁,它会阻止其他的查询、修改操作
3)可以对分区使用锁

Hive Command Locks Acquired
select … T1 partition P1 S on T1, T1.P1
insert into T2(partition P2) select … T1 partition P1 S on T2, T1, T1.P1 and X on T2.P2
insert into T2(partition P.Q) select … T1 partition P1 S on T2, T2.P, T1, T1.P1 and X on T2.P.Q
alter table T1 rename T2 X on T1
alter table T1 add cols X on T1
alter table T1 replace cols X on T1
alter table T1 change cols X on T1
alter table T1 concatenate X on T1
alter table T1 add partition P1 S on T1, X on T1.P1
alter table T1 drop partition P1 S on T1, X on T1.P1
alter table T1 touch partition P1 S on T1, X on T1.P1
alter table T1 set serdeproperties S on T1
alter table T1 set serializer S on T1
alter table T1 set file format S on T1
alter table T1 set tblproperties X on T1
alter table T1 partition P1 concatenate X on T1.P1
drop table T1 X on T1

4、如何开启关闭锁
hive 在 0.7 版本之后开始支持并发,线上的环境默认是用 zookeeper 做 hive 的锁管理,Hive开启并发功能的时候自动开启锁功能。

1开启

hive.zookeeper.quorum
zk1,zk2,zk3


hive.support.concurrency
true

2除此之外,还可以手动显式设置独占锁 将不能执行查询操作:
– 1)锁表
hive> lock table t1 exclusive;
– 表被独占锁之后,将不能执行查询操作:
hive> SELECT COUNT(*) FROM people;
conflicting lock present for default@people mode SHARED
FAILED: Error in acquiring locks: locks on the underlying objects
cannot be acquired. retry after some time

关闭锁
hive的锁在某些情况下会影响job的效率。在对数据一致性要求不高,或者已经明确了解到lock不会对job产生影响的情况下可以在session级别关闭lock的支持,又或者在表被任务循环持续读取时,insert 插入失败(建议脚本重跑一段时间范围数据时设置 sleep 间隔,避免长期持有锁,造成依赖表的任务调度失败)。我们可以通过 set hive.support.concurrency=false 参数在 session 中关闭锁,这个参数为 false 既能保证session忽略任何锁强行操作数据,又能保证session里的SQL对表不加任何锁。

场景1:离线下载分析商业cdn的qos job。
使用load data将数据导入hive中,hive的表按 dt,hour,domain进行明确分区,因此,是否有锁对数据的一致性影响不大,反而有了锁之后,job之间就会有锁竞争的问题(报错信息:conflicting lock present for table mode EXCLUSIVE)。

调整 job:

hive --database cdnlog -e "
set hive.support.concurrency=false;
load data local inpath ‘file’
OVERWRITE into table chinanetcenter_log_origin
partition(dt=‘2013-12-17’,hour=‘04’,domain=‘xxx’)
"
数据load时就不会有报错了,效率也高了不少

场景2:hive锁的几个配置,可以在锁冲突时 fail fast 或者 重试等待锁释放
hive.lock.numretries #重试次数
hive.lock.sleep.between.retries #重试时sleep的时间
hive默认的sleep时间是60s,比较长,在高并发场景下,可以减少这个的数值来提供job的效率

hive 处理表的流程 (CDH4.2.0)
1.首先对query进行编译,生成QueryPlan

2.构建读写锁对象(主要两个成员变量:LockObject,Lockmode)
对于非分区表,直接根据需要构建S或者X锁对象
对于分区表:(此处是区分input/output)
If S mode:
直接对Table/related partition 构建S对象
Else:
If 添加新分区:
构建S对象
Else
构建X对象
End

3.对锁对象进行字符表排序(避免死锁),对于同一个LockObject,先获取Execlusive

4.遍历锁对象列表,进行锁申请
While trynumber< hive.lock.numretries(default100):
创建parent(node)目录,mode= CreateMode.PERSISTENT
创建锁目录,mode=CreateMode.EPHEMERAL_SEQUENTIAL
For Child:Children
If Child已经有写锁:
获取child写锁seqno
If mode=X 并且 Child 已经有读锁
获取child读锁seqno
If childseqno>0并且小于当前seqno
释放锁
Trynumber++
Sleep(hive.lock.sleep.between.retries:default1min)

总结:

想要避免 Hive 锁造成的读、写失败问题,注意以下3点:

1、表建议设置分区,锁的粒度可以到分区,否则容易遭遇长时间锁表,尤其大字典表、单张全量表要注意。
2、建议脚本重跑一段时间范围数据时设置 sleep 间隔,避免长期持有锁,造成依赖表的任务调度失败。
3、我们可以通过 set hive.support.concurrency=false 来关闭锁,优先保证插入数据成功,虽然此时读数据会有问题。

Refer:https://juejin.im/entry/593f60a4da2f60006737b2db

猜你喜欢

转载自blog.csdn.net/weixin_40809627/article/details/86493590