异常表现:任一直没执行,具体报错如下:

Unbale to acquire IMPLICIT,SHARED lock appstore after 100 attempts.

Error in acquireLocks...

简单理解为获取100次,依旧无法获取到共享锁。

2.Hive 锁的类型与关系

hive 目前主要有两种锁,SHARED(共享锁 S)和 Exclusive(排他锁 X)。其中只触发S锁的操作可以并发执行,只要有一个操作对标或者分区触发了X锁,则该表或者分区不能并发的执行作业。

总结起来就是:

  1. 查询操作使用共享锁,共享锁是可以多重、并发使用的多个查询同时访问一个表是可以的,同时使用共享锁
     
  2. 修改表操作使用独占锁,它会阻止其他的查询、修改操作
    当修改表的时候,使用独占锁,所以此时没办法执行查询
     
  3. 可以对分区使用锁
    对一个分区上锁,不影响其他分区使用

以下情况会触发锁,以及它的类型和锁定范围如下:

Hive Command

Locks Acquired

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

3.如何开启锁机制

修改hive-site.xml,配置如下:

xml配置

<property>
<name>hive.zookeeper.quorum</name>
<value>zk1,zk2,zk3</value>
</property>
<property>
<name>hive.support.concurrency</name>
<value>true</value>
</property>

除此之外,还可以手动显式设置独占锁:

手动设置锁

1.锁表
hive> lock table t1 exclusive;
-- 表被独占锁之后,将不能执行查询操作:
hive> SELECT COUNT(*) FROM t1;
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

2.解除锁
hive> unlock table t1;

锁注释

注:Lock 是一种悲观的顺序化机制。它假设很可能发生冲突,因此在操作数据时,就加锁。

如果冲突的可能性很小,多数的锁都是不必要的。比如 Innodb 实现了一个延迟加锁的机制,来减少加锁的数量,提升性能,在代码中称为隐式锁(Implicit Lock),在本文中提到的 Hive锁默认都是隐式锁,除非手动加锁才是显式锁。

4.如何debug 锁

可以使用以下命令开始debug和排查锁问题:

debug锁

SHOW LOCKS <TABLE_NAME>;
SHOW LOCKS <TABLE_NAME> EXTENDED;
SHOW LOCKS <TABLE_NAME> PARTITION (<PARTITION_DESC>);
SHOW LOCKS <TABLE_NAME> PARTITION (<PARTITION_DESC>) EXTENDED;

测试一下发现,报锁管理器未指定错误,这个怎么回事呢?

show locks table_xxx;

FAILED:Execution Error,return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask.show Locks LockManager not specifed

查阅资料发现是需要配置 hive-site.xml文件中开启锁机制 (具体未进行测试)

那么如何开启锁机制呢
修改hive-site.xml,配置如下:

hive.zookeeper.quorum
zk1,zk2,zk3
hive.support.concurrency

true

5.如何关闭锁

hive的锁在某些情况下会影响job的效率。

在对数据一致性要求不高,或者已经明确了解到lock不会对job产生影响的情况下可以在session级别关闭lock的支持,又或者在表被任务循环持续读取时,insert 插入失败(建议脚本重跑一段时间范围数据时设置 sleep 间隔,避免长期持有锁,造成依赖表的任务调度失败)。

我们可以通过 set hive.support.concurrency=false 参数在 session 中关闭锁,这个参数为 false 既能保证session忽略任何锁强行操作数据,又能保证session里的SQL对表不加任何锁。

如:

set hive.support.concurrency=false 被锁的表就顺利解锁运行。

场景1:导入数据

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

调整:

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')
"

场景2:hive锁的几个配置,可以在锁冲突时 fail fast 或者 重试等待锁释放

hive.lock.numretries #重试次数

hive.lock.sleep.between.retries #重试时sleep的时间

hive默认的sleep时间是60s,比较长,在高并发场景下,可以减少这个的数值来提供job的效率。

6.总结

1.调查总结

本次事件是目前定位问题是,查询的时候一直申请不到锁,尝试获取锁超时导致。

具体什么原因导致无法获取锁,大概率是有排他锁占据,所以无法获取,具体是什么原因导致,暂时和平台没有定位到。(可能长时间插入数据错误等问题引起)

2.任务优化

目前在无事务要求情况下,可以不特殊配置  org.apache.hadoop.hive.ql.lockmgr.DbTxnManager

3.解决办法

非特殊情况下,可以直接设置 set hive.support.concurrency=false 参数在 session 中关闭锁 

这个参数为 false 既能保证session忽略任何锁强行操作数据,又能保证session里的SQL对表不加任何锁。