#title 프로시저 호출의 직렬화 [[TableOfContents]] ==== 문제 ==== 가끔씩 다음과 같은 질문을 받는다. ''프로시저를 여러 어플리케이션에서 호출합니다. 하지만 프로시저가 동시에 실행되는 것을 막고 싶습니다. 순차적으로 실행시킬 수는 없나요?'' 이러한 문제는 직렬화의 문제다. 2가지 솔루션이 있다. 1. COM의 개념을 이용한다. 2. LOCK으로 조절한다. 다음은 그 솔루션이다. ==== 솔루션1 ==== 1. app_reference 테이블을 만든다. (컬럼은 spname, refcount) 2. 프로시서 실행시 spname과 refcount를 검사해서 refcount가 1 이상이면 대기하고, 0이면 실행 3. 프로시저 맨 마지막에 refcount -1 해줌. 구현을 해보면.. {{{ use tempdb go --drop table app_reference create table app_reference ( spname nvarchar(255) primary key , refcount int ) --관리할 sp를 미리 등록함. insert app_reference values('usp_test', 0) go create proc usp_test as declare @refcount int while(1=1) begin update app_reference set @refcount = refcount = refcount + 1 where spname = 'usp_test' if @refcount = 1 break else waitfor delay '00:00:5' end select 1 waitfor delay '00:00:20' /* code.. */ update app_reference set refcount = 0 where spname = 'usp_test' go }}} 이 프로시저를 실행하면 약 20초간 실행을 대기한다. 20초 동안 다른 세션에서 app_reference를 조회해 보면 refcount가 1인 것을 확인 할 수 있다. 20초가 지나면 프로시저는 이후 작업을 진행하는데, 마지막 작업이 refcount를 -1 하는 것이다. 그러므로 최종적으로는 호출은 1회로 직렬화될 수 밖에 없다. 프로시저가 실행도중 오류를 일으킬 수도 있으므로 try ~ catch 를 이용하여 예외처리하고, 서비스 재시작시에 appreference의 refcount를 모두 0으로 초기화 시키는 프로시저를 호출하도록 설정해 놓으면 더 좋을 것이다. 비슷한 방법으로.. 프로시저 호출시마다 실행을 위한 순번표를 나눠주는 방법도 고려해 볼만 하다. ==== 솔루션2 ==== GETAPPLOCK or RELEASELOCK 을 이용한다.