개발자의 길/Database

[SQLite3][C++] database is malformed - DB 에 손상이 갔을 때.

토아드 2021. 7. 31. 23:40
반응형

 여느때와 같이 bug ticket 이 들어왔나 보고 있던 중에, 내 모듈이 SQLite DB 에 저장한 데이터를 읽을 수 없었다는 이슈가 있었다.

log 상으로는 어떠한 문제점도 보이지 않아서 설치된 DB 를 받아서 분석을 해 보았더니, 읽을 수 없었던 PK 를 SELECT 하려고 시도하니 database is malformed 라는 문구가 뜬 적이 있었다.

 

 해당 로그에 대한 자료를 찾아보니 pragma integrity_check 라는 PRAGMA 를 이용해서 DB 가 손상되었는지 확인 할 수 있었지만, 손상되었다는 정보만 얻고 별 소득이 없었다. 결국에 해결해야 되는 것은 내가 구현한 모듈에서 DB 를 손상시킬 수 있는 동작을 하고 있었다는 점이기 때문이다.

 

 우선 모듈은 DB 에 Read/Write 를 수행하고 있었고, 해당 DB 에는 다른 모듈들이 NFS 를 통해서 접근을 하고 있던 상황이었다. SELECT 와 INSERT OR REPLACE Query 만 날리는 단순한 상황이었는데 데이터베이스가 손상되었다고 하니 원인을 도무지 알 수 없었고, 재현테스트를 위해 같은 환경에서 Insert 와 select 를 매우 많이 수행하는 hard test 를 해 보았다.

 테스트용 프로그램을 실행하여 재현을 해 본 결과, 마찬가지로 DB 가 손상되는 문제가 있었고 SQLite association 에 도움을 요청했다. 메일로 현재 재현되는 상황을 최대한 자세히 설명 했더니 NFS 로 연결되어있는 DB 를 Read/Write 하면서 DB lock 이 정상적으로 동작을 하지 않기 떄문이라고 하였다.

 실제로 동작 과정을 자세히 보니 Write 를 하면서 journal file 이 생성된 상태에서 NFS 를 통해 연결된 다른 컴퓨터에서 Read 를 해버리면, journal file 이 사라지면서 DB 손상이 발생하는 것을 확인할 수 있었다. 아무래도 lock 이 정상동작하지 않아 NFS 로 연결된 다른 컴퓨터에서 journal filed 을 보고 rollback 을 하면서 문제가 생긴게 아닌가 싶었다.

 

 문제는 NFS 환경으로 연결된 SQLite3 DB 를 사용하지 않는 방향으로 수정을 했었다.

 

 사실 완전 처음 보는 증상이라 원인을 찾는데 시간이 좀 걸렸는데, 경험했던 내용들을 정리하다 보니 아래와 같은 페이지가 존재했다.

 

https://www.sqlite.org/howtocorrupt.html

 

How To Corrupt An SQLite Database File

Overview An SQLite database is highly resistant to corruption. If an application crash, or an operating-system crash, or even a power failure occurs in the middle of a transaction, the partially written transaction should be automatically rolled back the n

www.sqlite.org

 

찾아보니 NFS 에 대한 언급도 있었는데, 그때 이 문서를 봤었다면 예상보다 빨리 문제를 해결할 수 있었지 않았을까.. 싶다.

 

혹시 모르니 앞으로 SQLite3 를 이용한 개발을 한다면 해당 문서는 한번쯤 보는게 좋을 것 같다.

 

반응형