트랜잭셔널(ACID) 테이블의 HDFS 디렉터리를 통째로 복사해 다른 클러스터의 같은 이름 테이블 경로에 넣었는데 조회하면 0 건이 나온다. 파일은 분명히 있고 크기도 맞다.
hdfs dfs -ls /warehouse/tablespace/managed/hive/db.db/tbl
drwxr-xr-x ... /warehouse/.../tbl/delta_0000001_0000001_0000
drwxr-xr-x ... /warehouse/.../tbl/delta_0000002_0000002_0000
SELECT count(*) FROM db.tbl; -- 0
ACID 테이블의 데이터 디렉터리 이름에는 쓰기 식별자(write id)가 박혀 있다. delta_<min>_<max>_<stmt> 와 base_<writeid> 가 그것이다. 조회할 때 Hive 는 파일 시스템을 훑어 보이는 것을 다 읽는 것이 아니라, 메타스토어가 알려 준 유효 write id 목록에 드는 디렉터리만 읽는다.
write id 는 메타스토어의 트랜잭션 테이블에 들어 있다. 파일만 옮기면 대상 클러스터의 메타스토어에는 그 write id 들이 없으므로, 모든 delta 가 "유효하지 않은 것" 으로 걸러져 결과가 0 건이 된다. 파일 권한도 경로도 문제가 아니다.
그래서 이 경우에는 다음이 모두 듣지 않는다.
MSCK REPAIR TABLE db.tbl; -- 파티션 목록만 맞춘다. write id 와 무관
ALTER TABLE db.tbl SET LOCATION '...'; -- 경로만 바꾼다
REFRESH db.tbl; -- Impala 쪽 캐시일 뿐
MSCK REPAIR 는 비 ACID 파티션 테이블에서 디렉터리를 메타스토어에 등록하는 명령이다. ACID 의 write id 문제는 해결하지 못한다.
Hive 가 제공하는 정식 경로다. 메타데이터와 데이터를 함께 내보내고, 대상에서 읽어 들이면서 write id 를 새로 발급한다.
-- 원본 클러스터
EXPORT TABLE db.tbl TO '/tmp/export/tbl';
hadoop distcp hdfs://<SRC_NN>/tmp/export/tbl hdfs://<DST_NN>/tmp/export/tbl
-- 대상 클러스터
IMPORT TABLE db.tbl FROM '/tmp/export/tbl';
파티션 테이블은 파티션 단위로 내보낼 수 있다.
EXPORT TABLE db.tbl PARTITION (dt='20240920') TO '/tmp/export/tbl_20240920';
정기적으로 옮겨야 하면 Hive 의 복제(REPL DUMP · REPL LOAD)를 쓴다. 증분 복제를 지원하고 ACID 테이블을 대상으로 한다. 다만 두 클러스터의 Hive 버전과 보안 구성이 맞아야 하고 설정이 간단하지 않으므로, 일회성 이관에는 EXPORT·IMPORT 가 낫다.
두 클러스터의 버전 차이가 커서 위 방법이 막힐 때 쓰는 우회로다.
-- 원본에서 외부 테이블로 한 벌 뽑는다
CREATE EXTERNAL TABLE db.tbl_stage
STORED AS ORC
LOCATION '/tmp/stage/tbl'
AS SELECT * FROM db.tbl;
hadoop distcp hdfs://<SRC_NN>/tmp/stage/tbl hdfs://<DST_NN>/tmp/stage/tbl
-- 대상에서 외부 테이블로 붙인 뒤 ACID 테이블에 적재한다
CREATE EXTERNAL TABLE db.tbl_stage (...) STORED AS ORC LOCATION '/tmp/stage/tbl';
INSERT INTO db.tbl SELECT * FROM db.tbl_stage;
CTAS 로 뽑은 결과는 평범한 ORC 파일이라 write id 개념이 없다. 그래서 파일 이동이 통한다. 대신 한 번 더 적재하는 비용이 든다.
옮기기 전에 구조를 알아 두면 판단이 쉽다.
| 항목 | 내용 |
|---|---|
base_<writeid>/ |
압축(compaction)으로 만들어진 전체 스냅숏 |
delta_<min>_<max>_<stmt>/ |
삽입된 행 |
delete_delta_<min>_<max>_<stmt>/ |
삭제 표시 |
_orc_acid_version |
ACID 포맷 버전 표시 파일 |
ORC 파일 안의 행에도 operation · originalTransaction · bucket · rowId · currentTransaction 이라는 숨은 컬럼이 붙어 있다. 그래서 같은 스키마의 비 ACID 테이블에 그 파일을 그대로 붙여도 정상적으로 읽히지 않는다.
파일 내용을 직접 확인할 때는 ORC 도구를 쓴다.
hive --orcfiledump /warehouse/.../delta_0000001_0000001_0000/bucket_00000
hive --orcfiledump -d /warehouse/.../delta_0000001_0000001_0000/bucket_00000 | head
ACID 테이블로 만들려면 서버 쪽 설정이 갖춰져 있어야 한다. 대상 클러스터에서 먼저 본다.
SET hive.support.concurrency;
SET hive.txn.manager;
SET hive.compactor.initiator.on;
SET hive.compactor.worker.threads;
hive.txn.manager 가 DbTxnManager 가 아니면 트랜잭셔널 테이블이 정상 동작하지 않는다. compaction 워커가 0 이면 delta 가 계속 쌓여 조회가 느려진다.