한 상품에 딸린 마켓상품 열두 건이 전부 이미지가 깨져 있는 상태였다. 코드를 읽으며 원인을 추정했지만 후보가 여럿이라 하나로 좁혀지지 않았다.
Table of contents
코드가 낸 두 후보
첫째 후보는 파일 복사가 실패하는 경우였다. 미디어 레코드 복제와 실제 파일 복사가 분리돼 있어서 복사가 실패하면 레코드는 있고 파일은 없는 상태가 되는데 그것이 정확히 깨진 이미지의 모양이다.
둘째 후보는 동기화 전체가 하나의 트랜잭션으로 묶여 있다는 것이었다. 이미지 처리에서 예외가 나면 그 앞의 상품 정보 갱신까지 함께 롤백된다. 두 후보 다 그럴듯해서 코드만 읽어서는 어느 쪽인지 갈릴 수 없었다.
데이터가 가른 것
그래서 코드를 덮고 데이터베이스 쪽 사실을 봤다. 열두 건 전부 생성 시각과 갱신 시각이 같아서 만들어진 뒤로 한 번도 안 바뀐 상태였다.
같은 대상의 변경 이력을 세어 보니 그것도 0건이었다. 두 사실을 합치면 동기화가 한 번도 성공한 적이 없다는 결론이 나오고 첫째 후보였다면 상품 정보는 갱신됐어야 하므로 둘째로 확정됐다.
상위의 수정 이력
확인차 상위 상품을 보니 그 뒤로 두 번이나 수정된 이력이 있었다. 수정할 때마다 동기화가 돌았을 텐데 자식은 처음 만들어진 시각 그대로였다.
두 번의 동기화가 다 롤백됐다는 뜻이 된다. 첫째 후보를 완전히 배제하려고 미디어 레코드의 파일 크기도 비교했는데 같은 파일명인데 크기가 달라서 복제 시점의 원본과 지금 원본이 다른 파일이었고 그 사이에 마스터 이미지가 바뀐 것이었다.
복구를 막는 순환
이 진단의 결론이 생각보다 무거웠는데 상위를 아무리 수정해도 복구가 되지 않는다는 것이었다.
상위를 수정하면 동기화가 시작되고 이미지 처리에서 같은 예외가 나서 전체가 롤백되기 때문이다. 깨져 있어서 못 고치고 못 고쳐서 깨져 있는 순환이라 한 트랜잭션에 묶여 있는 한 부분 성공이 불가능했다.
그래서 복구는 상위 재수정만으로 불가능하고 동기화의 이미지 처리와 상품 정보 갱신을 분리하는 것이 선행돼야 한다고 보고했다. 나누면 상품 정보는 갱신되고 이미지 처리는 별도로 실패하며 다음 시도에서 이미지만 다시 하면 된다.
두 지표와 순서
이 건에서 다른 조사에도 쓸 진단 지표 둘을 얻었는데 생성 시각과 갱신 시각이 같다는 것과 변경 이력이 0건이라는 것이다.
둘이 같이 나오면 이 레코드에 아무 일도 안 일어났다는 강한 증거이고 무언가 실패했나 보다가 아니라 성공한 적이 없다로 확정된다. 조사 순서는 코드로 후보를 뽑고 데이터로 판별한 뒤 배제한 것도 따로 확인하는 것인데 코드는 이럴 수 있다까지만 말하고 실제로 그랬다는 것은 데이터가 말한다.
정리
- 코드로 후보가 좁혀지지 않으면 데이터베이스 사실을 본다
- 생성 시각과 갱신 시각이 같고 이력이 0건이면 성공한 적이 없다는 뜻이다
- 파일 크기 비교로 같은 파일인지 판별할 수 있다
- 전체가 한 트랜잭션이면 부분 성공이 불가능하다
- 깨져서 롤백되고 롤백돼서 못 고치는 순환이 생긴다
- 복구에 선행 조건이 있으면 그것부터 보고한다
- 코드는 이럴 수 있다까지만 말한다
- 실제로 그랬다는 것은 데이터가 말한다