shepherd's Blog

Trino - HIVE_TABLE_LOCK_NOT_ACQUIRED 본문

Data Engineering

Trino - HIVE_TABLE_LOCK_NOT_ACQUIRED

shepherd.dev 2023. 12. 25. 23:41

1. 문제 발생

Iceberg table에 데이터를 쓰는 ETL에서 에러가 발생하고 있어 확인해 보니 trino에서 EXTERNAL_ERROR - HIVE_TABLE_LOCK_NOT_ACQUIRED 에러가 발생하고 있었다.

2. 선조치

해당 테이블에 write 작업을 할 수 없는 상태라 우선 해결 방법이 있나 구글링하는데, hive table lock을 수동으로 해제하는 명령이나 방법을 찾질 못했다. 해결할 방법을 찾던 중 hive가 metadata를 관리하기 위해 database를 사용했던 게 기억나 hive database에 접속해서 table 목록을 살펴봤다.

오 public.hive_locks table이 보여 조회를 해보니 문제가 발생한 테이블의 lock이 남아 있는 걸 확인했다. lock 관련 테이블은 hive_locks 외에는 없는 거 같아 해당 테이블의 lock을 전부 지우고 다시 ETL을 돌려보니 정상적으로 데이터가 정상적으로 들어가기 시작했다.

3. 원인

사라지지 않은 lock은 trino coordinator에서 획득한 lock이었다. lock이 왜 남아서 문제를 일으키는지 trino coordinator와 worker의 로그를 확인해 봤지만, INFO Level의 로그로는 자세한 상황을 알 수 없었고, 비정기적으로 계속 발생했다.

수동 조치하며 원인을 찾던 중 worker가 자주 죽는 걸 확인했다.
worker가 왜 죽을까 생각하며 설정을 확인해 보니 trino cluster에 설정해둔 cpu 기반의 오토스케일러가 문제로 보였다.
k8s에서 trino cluster에 cpu 기반으로 오토스케일을 걸어 둔 상태로 쓰고 있었는데(trino helm chart 오토스케일러 설정), 오토스케일러 때문에 lock을 획득한 쿼리가 중간에 죽지 않았을까 하는 생각이 들었고, 다음 시나리오 기반으로 테스트를 해봤다.

  1. 쿼리 요청 증가
  2. cpu 사용량 증가로 worker 늘어남
  3. 쿼리 실행 완료
  4. cpu 사용량 감소로 worker 줄어듬
  5. k8s의 cpu 기반 오토스케일러라 쿼리 실행에 상관없이 worker 죽임
  6. 죽은 worker에 실행 중인 쿼리는 실패

큰 쿼리와 작은 쿼리를 여러 개 실행했고, 워커가 늘어나고 줄어드는 과정에서 남아 있던 큰 쿼리는 worker 통신 실패로 죽는 걸 확인했다.
이 에러의 끝이 보이는 거 같았다.

4. 조치

오토스케일러를 해제하고 쿼리가 실행되는 적정 수준의 리소스를 유지하도록 설정했다.
조치한 후에는 해당 문제가 발생하지 않고 정상적으로 운영되고 있다.

5. 남아있는 의문

trino coordinator에서 lock을 획득했다면 worker가 죽은 다음 coordinator에서 lock을 반납하는게 정상 동작일 거 같다.
이런 상황이라면 trino의 버그일 수도 있겠다는 생각이 들어 관련된 이슈를 찾아봐야 겠다는 생각이 들었다.

trino cluster를 사용하는데 cpu 기반의 오토스케일링은 맞지 않다는 생각이 든다. trino helm chart에서 제공하는 기본 오토스케일링 말고 worker의 trino query 실행 중인 상태를 확인하면서 실행되는 오토스케일이 가능할지 확인해 봐야겠다.

6. 남은 과제

  1. trino autoscaling 고도화 가능성 확인
  2. trino 비정상 종료 시 hive lock 처리 확인

'Data Engineering' 카테고리의 다른 글

spark streaming batch size  (0) 2023.07.21