게시글이 언제 수정됐는지 확인해 달라는 요청을 받았다. 이력 테이블은 있고 행도 8만 건 쌓여 있는데 그걸 보는 화면이 없었다.
Table of contents
Open Table of contents
쌓기만 하고 있었다
MySQL 테이블 구조를 보니 수정할 때마다 한 행이 들어가고 바뀐 내용이 통째로 저장되고 있었다. 문제가 두 가지였다.
먼저 볼 화면이 없다. 확인하려면 MySQL 에 직접 붙어야 하고, 그러면 요청이 올 때마다 개발자를 거쳐야 한다. 그리고 저장된 값이 수정 전후 전체라서 무엇이 바뀌었는지는 눈으로 비교해야 알 수 있다.
바뀐 항목만 남겼다
전체를 통째로 넣는 대신 바뀐 항목만 JSON 으로 남기게 바꿨다.
$changes = [];
foreach (['title', 'content', 'category', 'notice_yn'] as $f) {
if ($old[$f] != $new[$f]) {
$changes[$f] = ['from' => $old[$f], 'to' => $new[$f]];
}
}
JSON 이 비면 행을 아예 안 넣는다. 저장 버튼을 눌렀다는 이유로 다 이력이 되면 목록을 봐도 무엇이 실제로 바뀌었는지 안 보인다.
누가 바꿨는지도 같이 넣었다. 원래 그 컬럼이 없어서 이력을 봐도 주체를 알 수 없었다.
볼 화면을 만들었다
AdminLTE 로 만든 관리자 화면에 이력 보기를 넣었다. 게시글 번호로 최근 것부터 가져와 항목별로 보여 준다.
2013-12-28 15:22 admin2
제목: "공지사항" → "[중요] 공지사항"
분류: 3 → 1
2013-12-26 09:41 admin1
내용: (변경)
내용처럼 긴 항목은 변경됐다는 표시만 하고 눌렀을 때 펼치게 했다. 목록에서 한눈에 훑을 수 있어야 이력이 쓰인다.
컬럼 이름이 그대로 나오면 알아보기 어렵다. notice_yn 이 화면에 그대로 뜨면 보는 사람은 그게 무엇인지 모른다. 컬럼 이름과 사람이 읽는 이름의 대응표를 뒀다. 코드 값도 그대로 두지 않고 뜻으로 바꿨다. 이 대응표는 이력 화면 말고 다른 데서도 쓰여서 공용으로 뺐다.
쌓이는 속도와 보관 기간
이력이 계속 쌓이면 테이블이 커지니 얼마나 빨리 느는지 봤다. GROUP BY 로 최근 30일을 날짜별로 세어 보니 하루 200건쯤이고 1년이면 7만 건이다. 아직은 괜찮지만 언젠가 정리가 필요하다.
보관 기간을 1년으로 정하고 지난 것은 지우게 했다. 한 번에 다 지우면 오래 걸리고 잠금이 길어져서 DELETE 에 LIMIT 를 붙여 나눠 지운다. 보관 기간을 정하는 것과 이력을 남기는 것은 같이 정해야 했다. 기간을 안 정하면 영원히 쌓인다.
조회 조건에 인덱스도 넣었다. 게시글 번호로 찾고 날짜로 정렬하니 둘을 묶은 복합 인덱스를 걸었다.
정리
- 이력을 쌓기만 하고 볼 화면이 없으면 그 기록은 안 쓰인다
- 전체를 통째로 남기면 무엇이 바뀌었는지 알기 어렵다
- 바뀐 항목만
JSON으로 남기고 그것이 비면 행을 안 넣는다 - 누가 바꿨는지를 같이 남긴다. 없으면 이력을 봐도 주체를 모른다
notice_yn같은 컬럼 이름과 코드 값은 사람이 읽는 말로 바꿔서 보여 준다- 쌓이는 속도를 재고 보관 기간을 같이 정한다. 안 정하면 영원히 쌓인다
- 지울 때는
DELETE에LIMIT를 붙여 나눈다. 한 번에 다 지우면 잠금이 길어진다 - 조회 조건과 정렬 컬럼을 묶어 인덱스를 건다