前些天亲身经历了一次hive表锁表经历,现在有空,记录一下。
照例先介绍下背景,此次涉及到 两张hive表 table_a ,table_b ,两张表都是外部表,table_b的生成依赖于table_a,调度执行用的是 dolphinscheduler。
此次经历发生在项目上线前hive表刷数据阶段,由于两张表新增了字段,需要全量刷新数据后同步给后端使用。
我当时的操作是这样的,
- 数据脚本上线后,在dolphinscheduler中启动工作流,相关任务开始依次执行。
- 执行过程中,table_a生成后,发现 table_a 的生成sql有问题(任务没有失败,测试数据样本量不够,缺少对某个字段特定值的特殊处理),此时工作流还在正常执行中。我发现sql有问题后,在dolphinscheduler停止工作流。
- 在观察到 dolphinscheduler工作流停止后,修改sql准备重新执行,然而,此时工作流实际并没有完全停止。dolphinscheduler停止工作流是等待当前执行中任务完成后才会停止,(并不会杀掉相关任务进程,更不会停止yarn进程,坑),状态在移动到标识上时才会显示为准备停止。然后我就中招了,以为它停止了,实际并没有,此时table_b正在执行中
- 发现table_a数据不对,自然要清空数据后重新执行,由于是外部表,我所做的操作是 先 hdfs dfs -rm -r 掉分区对应目录,然后在hive中,执行 alter table table_a drop partition() (不规范的操作,不要学我,直接 insert overwrite table_a就行)。
第一步很顺利就执行成功了,但第二步没有反应(因为生成table_b用到table_a,此时table_a有锁)。但当时并没有想到锁表(以为工作流已经停了),只是单纯以为卡了或发生了其他问题,此时,hdfs中没有该分区的目录,在hive中,show partitions 时有该分区,select 时数据为null - 在我的一通操作下自然而然产生了死锁, table_b执行中给table_a加了shared 锁,我直接删除hdfs文件,又导致 table_b 执行进行不下去(按理说到这一步时table_b应该会报错失败,然鹅并没有,一直在重试),而table_b的重试又一直给table_a加锁,导致drop parititon 失败无反应。等待半小时后,drop partition 依然失败,尝试删表重建,依然失败,想到了是不是锁表。show locks table_a,嗯,没错,锁表了,找到对应的进程,杀掉,然后重新 drop partition ,成功,问题解决。
不是什么大问题也不是什么难问题,但由于从没遇到过这种问题,思路没转过来,浪费了一个多小时,导致上线推迟。特此记录一下。
Life is fantastic!