异常表现:任一直没执行,具体报错如下:
Unbale to acquire IMPLICIT,SHARED lock appstore after 100 attempts.
Error in acquireLocks...
简单理解为获取100次,依旧无法获取到共享锁。
2.Hive 锁的类型与关系
hive 目前主要有两种锁,SHARED(共享锁 S)和 Exclusive(排他锁 X)。其中只触发S锁的操作可以并发执行,只要有一个操作对标或者分区触发了X锁,则该表或者分区不能并发的执行作业。
总结起来就是:
- 查询操作使用共享锁,共享锁是可以多重、并发使用的多个查询同时访问一个表是可以的,同时使用共享锁
- 修改表操作使用独占锁,它会阻止其他的查询、修改操作
当修改表的时候,使用独占锁,所以此时没办法执行查询
- 可以对分区使用锁
对一个分区上锁,不影响其他分区使用
以下情况会触发锁,以及它的类型和锁定范围如下:
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配置
|
除此之外,还可以手动显式设置独占锁:
手动设置锁
|
锁注释
注:Lock 是一种悲观的顺序化机制。它假设很可能发生冲突,因此在操作数据时,就加锁。
如果冲突的可能性很小,多数的锁都是不必要的。比如 Innodb 实现了一个延迟加锁的机制,来减少加锁的数量,提升性能,在代码中称为隐式锁(Implicit Lock),在本文中提到的 Hive锁默认都是隐式锁,除非手动加锁才是显式锁。
4.如何debug 锁
可以使用以下命令开始debug和排查锁问题:
debug锁
|
测试一下发现,报锁管理器未指定错误,这个怎么回事呢?
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.concurrencytrue
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)。
调整:
|
场景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对表不加任何锁。