좀 난감한 예외처리&재시도..
글쓴이: munamuna / 작성시간: 목, 2009/01/15 - 2:16오후
안녕하세요.. __);
좀 난감한 재시도 처리가 있어서 조언을 좀 듣고자 합니다.
다음과 같은 COM을 이용한 DB처리 로직을 만들었습니다.
try { <blnk> TESTHR(pConnection.CreateInstance(__uuidof(Connection))); TESTHR(pRstEmployees.CreateInstance(__uuidof(Recordset))); pConnection->Open(strCnn, "", "", adConnectUnspecified); pRstEmployees->Open("K_CSVOUT",_variant_t((IDispatch *) pConnection, true),adOpenKeyset,adLockOptimistic,adCmdTable); pConnection->BeginTrans(); pConnection->Execute(sSQL, NULL,adCmdText); hr = pConnection->CommitTrans(); if (FAILED(hr)) { pConnection->RollbackTrans(); _com_issue_error(hr); } pRstEmployees->Close(); pConnection->Close(); } catch(_com_error &e) { ::CoUninitialize(); return ERR; }
그런데, 이게 오늘 아침 "실패할경우 0.1초 대기후에 최대 50회까지 재시도 할것"으로 사양이 바뀌었습니다.
근데 보시면 아시듯이 인스턴스 생성"CreateInstance()"을 제외하고는
첫 작업이 성공해야 다음 작업.. 다음 작업이 성공해야 그 다음.. 이런식인데요..
두번째 작업에서 실패했는데, 재시도를 첫번째 작업부터 하면 오류가 날게 뻔하니..
try { TESTHR(pConnection.CreateInstance(__uuidof(Connection))); TESTHR(pRstEmployees.CreateInstance(__uuidof(Recordset))); } catch(e) { // 오류처리 } dbRetry: try { if( nFlag != Open1성공 ) { pConnection->Open(strCnn, "", "", adConnectUnspecified); nFlag |= Open1성공; } if( nFlag != Open2성공) { pRstEmployees->Open("K_CSVOUT",_variant_t((IDispatch *) pConnection, true),adOpenKeyset,adLockOptimistic,adCmdTable); nFlag |= Open2성공; } if( nFlag != BeginTrans성공) { pConnection->BeginTrans(); nFlag |= BeginTrans성공; } if( nFlag != Execute성공) { pConnection->Execute(sSQL, NULL,adCmdText); nFlag |= Execute성공; } if( nFlag != CommitTrans성공) { hr = pConnection->CommitTrans(); if (FAILED(hr)) { pConnection->RollbackTrans(); _com_issue_error(hr); } else { nFlag |= CommitTrans성공; } } } catch(e) { errCnt++; if(재시도횟수이내라면) 0.1초 대기; goto dbRetry; }
정작 이렇게 만들어는 놨는데..
어쩌다 발생할지도 모르는 오류를 처리하기 위한 로직으로는 if문이 너무 많은듯 싶습니다.
혹시 간결하게 바꿀 수 있는 아이디어가 있으시거나..
댁이 COM을 잘 몰라서 그러는데. 이런이런 오류체크는 필요없다거나..
COM에는 이런이런 방법이 있다.. 라는 등등 의견 부탁드립니다.
그럼.. 즐개발 되십시요.. __);
Forums:
if 문 뒤에 nFlag 랑은
if 문 뒤에 nFlag 랑은 != 가 아니라 !( A & B ) 겠지요?
논리적으로 특별히 더 고칠건 없어보입니다. 그리고 저정도 if 문은 그다지 부하도 아닙니다.
Neogeo - Future is Now.
Neogeo - Future is Now.
네.. __);
요청 한번에 조립해서 넣어줘야 하는 데이터양이 2400건 정도 되서 걱정이 좀 되서요..
2400건이면
db부하도 생각하실겸 2400건을 처리후 commit을 하는것으로 변경해주세요 ^^:
그리고 50번 실패라는 어떤경우인가여 insert 실패를 말씀하시는건가요 ^^;
조금 부연설명 부탁드립니다.
안녕하세요.. __);
먼저 50번 실패라는 것은 "어떠한 경우이건 간에 DB에 데이터를 써 넣을 수 없었을때"라고 하더군요.
설사 DB파일이 없어도 50회 재시도를 하라는 것입니다.
그리고 이미 인수인계 받은 시점에서는 제가 DB작성하는 DLL을 제공하고,
VB쪽에서 필요한 데이터를 뽑아 제 DLL을 콜해주면..
저는 그 데이터를 이러저러한 계산처리를 완료한 후에 DB에 데이터를 작성합니다.
여러개의 vb 프로세스가 움직이며 데이터를 처리해서 바로바로 넘겨주기 때문에 이렇게 만들었다고 하네요.
그정도로 큰 규모로
그정도로 큰 규모로 data 를 넣고 중간에 fail 나면 roll back 해야하는 경우라면 차라리 SP ( stored procedure ) 를 사용하시는게 올바른것 같습니다.
DB DATA 의 integrity 는 전문가(?) 에게 맡기는게 정석 아닐까요?
애초에 상황묘사가 좀 잘못된것 같습니다. 50회 반복실행여부는 여하튼 DB에 부하가 걸릴때 실패할경우를 대비해서 하시는 것 같은데, 실행하시는 stmt 내용이 뭔진 모르겠지만, 50회 반복하나 안하나 별 차이가 없고 오히려 50회 반복해서 부하만 더 심해질것도 같습니다. ( 이미 DB 에 부하가 걸려서 접속을 안받을 정도인데, 혹은 stmt 실행이 timeout 날 정도인데, 0.1초 쉬고 반복한다고해서 좋아질지는 좀 의문이군요. 차라리 무한 반복이면 또 모르겠습니다만.... )
그리고 2400 건이나 data를 쏟아부어버리는 상황이면 매번마다 접속을 새로 하는것도 굉장한 삽질입니다. 접속을 유지하시거나 connection pool 을 이용하시는게 훨씬 현명한 방법입니다. ( 접속이 날라가지 않았나 check 하는쪽이 훨씬 낫겠지요. )
묘사하신 상황이외에 제가 임의로 상황을 가정해보면, 위의 stmt 실행을 2400 번 반복하다가 중간에 하나가 펑크나면 줄줄이 뒤에 data가 못 들어가는 상황이어야 한다던가, 2400 개가 다 commit 되지 않으면 rollback 되어야 한다던가 하는건 C++ 의 COM 수준을 넘어서는 요청이 아닐까 생각합니다.
DBA 랑 상황을 자세히 상의해보시는게 좋을 것 같습니다.
Neogeo - Future is Now.
Neogeo - Future is Now.
저도 이거 웬지 웃기다고 생각은 하고 있습니다.;;
제가 DB를 잘 알지 못하는지라 뭐라 명확하게 이상하다고는 할 수 없지만..
이거 뭔지 좀 웃깁니다.
처음 이 DLL을 봤을때, 로그 한줄을 쓰려면..
설정파일 클래스 생성 -> 설정파일 오픈 -> 한줄한줄 읽어가며 설정1 취득 -> 설정파일 닫음 -> 설정파일 다시 오픈 -> 다시 처음부터 한줄한줄 읽어가며 설정2 취득 -> 설정파일 닫음 -> (..이짓을 설정 27개 취득할때까지 반복) -> 읽어들인 설정중 로그저장 경로 취득 -> 로그작성 클래스 생성 -> 로그 작성 함수 콜 -> 로그파일 오픈 -> 오픈실패면 로그파일 생성(ㅡㅡ); -> 로그파일을 한줄한줄 읽어가며 라인수 취득 -> 로그작성 -> 로그파일 닫음 -> 로그 작성 클래스 제거 -> 설정파일 클래스 제거
농담한줄 안보태고.. 그냥 로그 한줄 작성하는데 이짓을 다 하고 있었습니다.. ㅡㅡ;
처음에는 설정파일을 무슨 실시간으로 읽어야 되는줄 알았습니다.. ;; 아니더군요..
DB도 결국 하나의 DB파일을 여러개의 vb프로그램(이건 동일한 프로그램을 최대 5개까지 복사해서 실행시킵니다)에서 사용을 합니다.
왜 이렇게 해요(쓰레드를 안쓰고 동일한 프로세스를 5개 실행시키는지..)? 라고 물어봤더니..
작업속도를 빠르게 하기 위해서랍니다...(정말 빨라지는 건지는 저도 잘 모르겠습니다.. ㅡㅡ?)
공유메모리를 사용하던지 IPC를 쓰자고 했더니.. 눈에 안보이니 예상치못한 이상이 생기면 알 수 없으니 공유메모리나 IPC는 안된답니다.
느려도 안전이 최고라고 하네요.
흠.. 전력관련 일이니 안전이 최고라는 말이 이해가 안되는 것도 아닙니다만..
요청 하나 내리면 처리가 2시간이나 걸리는 이유를 알듯 합니다...;;
말씀
말씀 하신상황대로라면, 더 '안전' 하지도 않습니다.
차라리 1개의 프로그램이 다 처리하는게 안정성면에서는 훨씬 나을수도 있습니다.
이유는, 만약 프로그램하나가 DB 접속 물고 뻗어버리면 나머지 4개의 process 는 손가락만 빨고 있을 공산이 크게 되겠군요.....
( 뭔가 Access File DB 같은걸 쓰시나 봅니다. DBMS 따로 없이 파일을 ODBC 같은것으로 접속해서 쓰시는 모양새 같은데.. )
Neogeo - Future is Now.
Neogeo - Future is Now.
네..access쓰고 있습니다.
여기서 한번 더 놀라시면 되는 것이지요..;;
-_- 놀라지 않습니다.
-_- 놀라지 않습니다. 이미 묘사하신 상황으로 충분히 짐작했습니다.
축하드립니다. 일단 적당히 믿어주는척 하면서, 요구하신 사항에 맞게 일을 해주시고 책임소지운운할 일이 생기면 논리를 갖추어 디자인을 다시 엎고 만들 계획을 뒤로 생각해두시면 되겠습니다.
ADO 던 ODBC API던 ... 애초에 COM 을 왜 쓰려고 하는지도 의문이군요...................
여하튼 열심히 하시길!
Neogeo - Future is Now.
Neogeo - Future is Now.
댓글 달기