전표 번호가 1002 다음에 1011로 이어지고 1003부터 1010이 보이지 않으면, 가운데 전표가 지워진 것처럼 보입니다. 메인 메모리 버퍼링을 쓰는 번호 범위라면 그 번호가 확정된 전표에 한 번도 부여되지 않았을 수 있습니다. 건너뛴 번호는 삭제 기록이 아니라, 번호가 어떻게 나누어졌는지를 먼저 묻는 단서입니다.
아래 1000번대는 그 동작을 따라 만든 가상 숫자입니다. 회사 시스템에서 조회하거나 실행한 결과가 아닙니다. 버퍼 방식과 화면 이름은 제품과 릴리스마다 다를 수 있습니다. 병렬 버퍼링은 롤백 뒤 번호가 되돌아오므로, 아래에서 말하는 상실과 다릅니다.
메모리에 번호가 있을 때와 없을 때
번호 범위 버퍼는 번호를 자주 줄 때 매번 데이터베이스를 기다리지 않으려고 씁니다. 메인 메모리에 번호가 남아 있으면 그 요청은 버퍼에서 번호를 하나 받고, NRIV를 읽지 않습니다. 버퍼가 없으면 한 사용자가 번호를 받은 뒤 커밋할 때까지 다음 사용자가 같은 번호 줄을 기다립니다.
번호를 메모리에서 꺼내는 요청과, 비어 있는 묶음을 NRIV에서 다시 채우는 요청은 같은 동작이 아닙니다. 메모리에 쓸 번호가 없으면 다릅니다. 인스턴스를 막 시작했거나 이전 묶음을 다 쓴 뒤의 요청은, 예약해 둔 개수만큼을 NRIV에서 새 묶음으로 올립니다. 그때 그 구간의 사용 번호도 같은 개수만큼 늘어납니다. 표준으로 제공되는 번호 범위 오브젝트는 대부분 이 방식을 쓰지만, 지금 보는 전표의 오브젝트는 SNRO나 SNUM에서 따로 확인합니다. 예약 개수는 오브젝트마다 다르고, 자주 번호를 주는 경우 10에서 1,000이 흔합니다.
이 순서는 번호를 하나 줄 때 NUMBER_GET_NEXT를 쓰고, 버퍼를 무시하지 않으며, 메인 메모리 버퍼가 켜진 경우입니다. 애플리케이션이 버퍼를 우회하면 순서가 달라질 수 있습니다.
새 묶음은 전표가 되기 전에 번호부터 건너뜁니다
가상 예시는 내부 채번, 버퍼 개수 10, 마지막 사용 번호 1000, 다음 번호 1001을 가정합니다. 메모리에 묶음이 없는 첫 요청은 1001부터 1010을 올리고 사용 번호를 10 증가시킵니다. 그다음 요청은 이 묶음이 떨어질 때까지 메모리에서 번호를 받습니다.
새 묶음을 채울 때는 번호를 요청한 작업에 넘기기 전에 데이터베이스에 먼저 반영합니다. 서버가 내려가면 메모리에 남은 번호가 통째로 사라질 수 있고, 간격은 활성 서버마다 버퍼 개수 규모로 커질 수 있습니다. 1001과 1002만 확정된 뒤 인스턴스가 재시작되면 1003부터 1010은 공급에서 사라집니다. 그 번호는 삭제된 전표가 아니라, 확정 전표에 부여되지 못한 번호입니다.
“1003 전표가 없다”만으로 삭제나 아카이브를 결론 내릴 수 없습니다. 확정 전표가 없고, 그 구간을 올린 뒤 서버가 재시작했다면 버퍼에서 생긴 간격일 수 있습니다. 그래도 모든 누락의 원인이 버퍼는 아닙니다. 다른 구간, 다른 연도, 다른 번호 범위 오브젝트도 가능합니다.
서버가 둘이면 큰 번호가 먼저 생길 수 있습니다
인스턴스가 여러 개면 각 인스턴스가 구간마다 자기 버퍼를 갖습니다. 프로그램이 어느 인스턴스에서 도느냐에 따라 번호가 다른 버퍼에서 나오고, 번호를 시간순으로 정렬할 수 없습니다.
앞의 예시에서 A가 1001부터 1010을 올리고 1001과 1002만 확정했다고 하겠습니다. B가 이어서 요청하면 다음 묶음 1011부터 1020을 자신의 메모리로 올립니다. B가 1011을 확정하면 목록에는 1001, 1002, 1011이 있고 1003부터 1010은 없습니다. 1011이 1003보다 나중인지는 번호만으로 알 수 없습니다. 1003은 A의 메모리에 남아 있을 수도 있고, A의 재시작으로 이미 사라졌을 수도 있습니다. 만든 순서는 전표의 입력 시각처럼 시간을 기록한 값으로 보고, 번호의 크기는 어느 서버의 묶음에서 나왔는지로 읽습니다.
롤백한 번호가 돌아오는지는 버퍼 크기로 갈립니다
메인 메모리 버퍼에서 이미 꺼낸 번호는 롤백해도 돌아오지 않아 간격이 생깁니다. 간격이 없어야 하거나 법으로 허용되지 않는 번호라면 이 버퍼를 쓰지 않는 편이 맞습니다. 버퍼가 1보다 크면 커밋 뒤에도 묶음은 메모리에 남습니다. 그 커밋이 묶음 전체를 전표로 만든 것은 아니며, 롤백하면 번호는 사라집니다. 버퍼가 1이면 오름차순은 유지되지만 롤백한 번호는 사라져, 시간순이라도 빠짐없지 않을 수 있습니다. 버퍼가 0, 즉 버퍼링을 하지 않으면 롤백해도 번호를 다시 쓸 수 있습니다.
버퍼가 크면 재시작 때 버리는 번호도 많아집니다. 버퍼를 쓰느냐의 차이가 개수 차이보다 큽니다. 여기서 적당한 개수를 정하지는 않습니다. 병렬 버퍼링은 묶음을 NRIVSHADOW에 두고, 롤백이나 재시작 뒤 번호를 되돌립니다. 무간격, 시간순, 버퍼링을 동시에 만족하지도 못합니다.
빠진 번호를 보기 전에 적어 둘 질문
빈 번호 때문에 전표를 복구하거나 버퍼를 비우지 않는 편이 안전합니다. SM56은 현재 서버에 남아 있는 버퍼를 보여 줍니다. 클라이언트, 오브젝트, 하위 오브젝트, 구간, 연도, 외부 번호 여부, 현재 번호, 버퍼에서 줄 수 있는 끝 번호가 보입니다. 재시작으로 이미 사라진 번호의 이력은 아닙니다. 구간을 바꾸거나 지우면 버퍼가 비워지기도 하고, 전역으로 비우면 모든 서버의 엔트리가 사라집니다. 간격을 메우려고 비우면 아직 쓰지 않은 번호가 또 버려질 수 있습니다.
- 이 번호는 어느 오브젝트의 어느 구간인지. 자릿수만으로 오브젝트를 정하지 않습니다.
- SNRO 또는 SNUM에서 메인 메모리 버퍼링이 켜져 있는지, 예약 개수는 몇인지.
- 그 번호의 확정 전표가 실제로 없는지. 다른 연도나 구간과 헷갈린 것은 아닌지.
- 서버가 둘 이상이면 번호 크기를 만든 순서로 읽고 있지는 않은지.
- 재시작이나 롤백이 있었을 수 있는지. 확정 전표가 없으면 삭제보다 미부여를 먼저 의심합니다.
간격이 허용되지 않는 문서라면 버퍼를 쓰지 않는 쪽을 먼저 검토합니다. 설정을 바꿀지는 애플리케이션과 법적 요건을 아는 사람의 결정이며, 이 예시는 운영 설정을 바꾸라는 지시가 아닙니다. 건너뛴 번호는 삭제 증거가 아닙니다. 어느 서버의 묶음에 올라갔고, 확정 전에 재시작이나 롤백으로 버려졌는지를 먼저 구분합니다.
이 기록에 대화를 더해 주세요.
궁금한 점, 다른 접근, 직접 해 본 결과를 나눠 주세요.
로그인 상태 확인 중…
댓글을 불러오는 중…