테일스케일, DB 손상 19차례 원인이 16년 된 SQLite WAL 리셋 버그였다고 발표
- Tailscale는 작년 8월부터 6개월간 19차례 SQLite 데이터베이스 손상을 겪었고 원인은 16년 된 WAL 리셋 버그로 밝혀짐
- 버그는 여러 커넥션이 동시에 열려 있을 때만 발생하는 타이밍이 매우 좁은 데이터 레이스로, SQLite 개발자도 자연 발생으로 재현하지 못해 강제로 트리거하는 테스트 로직을 추가해야 했음
- Tailscale는 체크포인팅을 수동으로 매우 적극적으로 수행하는 구조 때문에 다른 SQLite 사용자보다 이 버그를 만날 확률이 높았음
- Tailscale는 오픈소스 SQLite VFS shim 개발에 자금을 지원해 레이스 컨디션을 거의 즉시 격리하는 데 도움을 받음
- 각 샤드는 단일 Go 프로세스가 독점 접근하는 SQLite DB를 쓰는 단일 작성자 구조이며, 손상 발생 시 해당 샤드의 컨트롤 플레인 전체가 복구될 때까지 다운되어 신규 기기 연결 등이 영향을 받음
Hacker News opinions
오픈소스 SQLite VFS shim 개발 비용을 대줘서 레이스 컨디션을 거의 바로 잡아냈다는 얘기 재밌네. 회사가 이런 특정 디버깅 툴 만드는데 돈 대는 사례는 흔치 않음.
테일스케일은 원래 이런 일 처리하는 방식이 괜찮더라, 리더십이 제대로 박혀있는 느낌임.
테일스케일이 쓰는 Go용 SQLite 드라이버가 뭐야?
이거 쓴다더라.
글 잘 썼다. 영리기업인데 SQLite에 지원 계약까지 맺었다는 것도 마음에 듬. 문제 해결됐어도 계속 유지했으면 좋겠음.
'단일 Go 프로세스가 독점적으로 접근하는 구조라 SQLite 쓰기엔 이상적'이라는 문장 보고 writer랑 checkpointer가 같은 커넥션에서 도는 줄 알았는데, SQLite 공식 문서 보니까 이 버그는 커넥션이 여러 개 열려있어야만 터지는 거더라. 그러니 writer랑 checkpointer가 다른 스레드에서 돌았다는 소리임.
포스트가 버그 심각성을 좀 축소해서 쓴 것 같음. '일반적인 사용에서는 잘 안 일어난다'고 했지만 실제로 대형 고객한테 터졌잖아. 개발자들도 자연발생으로 재현 못해서 강제로 트리거하는 테스트 로직까지 추가했다더라.
'왜 유독 테일스케일이 이 버그를 만났는지' 설명한 부분을 왜 강조 안 했는지 이상함. 체크포인팅을 수동으로 아주 적극적으로 하니까 확률이 높았다고 본문에 명시돼 있는데.
DB 손상 나면 그 샤드 전체 컨트롤 플레인이 죽는다는 부분 보고 전형적인 단일 장애점이네 싶었음.
DB 손상을 단일 장애점으로 안 만들려면 뭘 할 수 있지? 딱히 떠오르는 해법이 없음. 이런 손상은 흔한 장애 유형으로 안 치는 경우가 많아서 설계에 반영 안 하는 듯.