정산 자료를 확인하는데 숫자가 안 맞았다. 화면에는 1,204건인데 조회하면 890건이다. 같은 표를 보는 줄 알았다.
Table of contents
Open Table of contents
표가 둘이었다
목록을 봤다.
SHOW TABLES LIKE 'settle%';
settle
settlement
settle_bak_20140801
settle 과 settlement 가 있다. 각각 세어 봤다.
SELECT COUNT(*) FROM settle; -- 890
SELECT COUNT(*) FROM settlement; -- 1204
화면은 settlement 를 보고 내 쿼리는 settle 을 봤다. 조회할 때 오류는 전혀 나지 않았다 — 이름이 존재하니 조회는 정상으로 돌고 건수만 다르다.
원인 — 이름을 바꾸다 만 것
코드에서 어느 것이 쓰이는지 찾았다.
$ grep -rn "'settle'" --include=*.php application/ | wc -l
2
$ grep -rn "'settlement'" --include=*.php application/ | wc -l
31
settlement 가 실제로 쓰이고 settle 은 두 곳에서만 쓰인다. 그 두 곳을 열어 보니 지금은 안 도는 옛 배치였다.
마지막 갱신 시각도 봤다.
SELECT MAX(reg_date) FROM settle; -- 2014-03-11
SELECT MAX(reg_date) FROM settlement; -- 2014-12-22
settle 은 아홉 달 전에 멈췄다. 이름을 바꾸다 말고 옛 표를 안 지운 것이었다.
INFORMATION_SCHEMA.TABLES 의 UPDATE_TIME 도 같이 봤는데 이 값만 믿을 수는 없었다. 매뉴얼에 서버를 다시 띄우거나 그 표가 InnoDB 데이터 딕셔너리 캐시에서 밀려나면 값이 남지 않는다고 적혀 있다 — 살아 있는 표가 NULL 로 보일 수 있다는 뜻이라 쓰는 곳과 MAX(reg_date) 를 함께 봤다.
옛 표를 정리했다
바로 지우지 않고 이름을 바꿨다.
RENAME TABLE settle TO _deprecated_settle_20141222;
앞에 표시를 붙이면 실수로 조회할 일이 없어진다. 그리고 그 이름으로 조회하는 코드가 남아 있으면 ER_NO_SUCH_TABLE 이 난다 — 조용히 틀리는 대신 소리를 내게 만든 것이다.
한 달 두고 아무 문제가 없으면 지우기로 했다. 옛 배치 두 곳도 확인해서 하나는 안 도는 것이라 지웠고 하나는 settlement 를 보게 고쳤다.
같은 상태가 더 있는지 봤다
이름이 비슷한 표를 찾았다.
SELECT table_name, table_rows, create_time, update_time
FROM information_schema.TABLES
WHERE table_schema = 'shopdb'
ORDER BY table_name;
목록을 보니 몇 쌍이 있었다.
order_item / order_items ← 복수형 차이
product_img / product_image ← 축약 차이
user / users ← 복수형 차이
세 쌍이었고 전부 한쪽이 옛 것이라 갱신이 멈춰 있었다. TABLE_ROWS 는 참고만 했다 — InnoDB 에서 이 값은 옵티마이저가 쓰는 어림수라 실제 건수는 COUNT(*) 로 따로 세야 한다.
UPDATE_TIME 으로 정렬해서 오래된 것도 봤다.
SELECT table_name, table_rows, update_time
FROM information_schema.TABLES
WHERE table_schema = 'shopdb' AND update_time < DATE_SUB(NOW(), INTERVAL 90 DAY)
ORDER BY update_time;
11개가 나왔다.
- 5개는 옛 표 (정리 대상)
- 3개는 코드 표 (원래 안 바뀜)
- 3개는 백업 (정리 대상)
코드 표는 정상이라 남기고 나머지 8개를 정리했다.
설정 — 이름 규칙과 확인 절차
앞으로 이런 일이 없게 규칙을 뒀다.
표 이름은 단수형을 쓴다 order_item (order_items 아님)
줄임말을 쓰지 않는다 product_image (product_img 아님)
옛 것을 남길 때는 접두사를 붙인다.
_deprecated_{원래이름}_{날짜}
_bak_{원래이름}_{날짜}
접두사가 있으면 목록에서 앞쪽에 모이고 실수로 조회할 일이 준다.
조회할 때 표 이름을 확인하는 습관도 들였다.
SHOW TABLES LIKE 'settle%';
SHOW TABLES LIKE 한 줄이면 비슷한 이름이 있는지 보인다. 처음 보는 스키마에서 조회할 때 특히 유용했다.
정리
- 이름이 한 글자 다른 표가 있으면 조회가 조용히 틀린다
- 이름이 존재하면 오류 없이 다른 결과가 나온다
grep -rn으로 어느 것이 실제로 쓰이는지 센다MAX(reg_date)를 보면 멈춘 표가 드러난다UPDATE_TIME은 재시작하거나 캐시에서 밀려나면 남지 않는다TABLE_ROWS는 InnoDB 에서 어림수라COUNT(*)로 따로 센다DROP TABLE말고RENAME TABLE로ER_NO_SUCH_TABLE이 나게 한다information_schema로 갱신이 멈춘 표를 한 번에 찾는다- 코드 표처럼 원래 안 바뀌는 것과 구분한다
- 이름 규칙을 정하고 옛 것에는 접두사를 쓴다
- 조회 전에
SHOW TABLES LIKE로 비슷한 이름을 확인한다