2010-08-14 2 views
2

임시 테이블을 비우고 bcp를 통해로드 한 다음 프로덕션 테이블로 이동하기 전에 행을 수정합니다.MSSQL bcp를 임시 테이블로로드

  1. 잘라 내기 테이블 TEMP1
  2. BCP db.schema1.temp1에서 import1.txt -h "TABLOCK"
  3. 간부 sp_modify_temp1_rows_move_to_production_table

내 질문은 어떻게 : 명령은 다음과 같을 것 이 모든 것을 하나의 트랜잭션으로 실행할 수 있습니까? 반드시 롤백해야 할 필요는 없지만 격리를 제공하십시오.

여기에 상상의 시나리오가 있습니다. User1은 import1.txt를로드합니다 (이 작업의 수행 세부 사항, 1 ~ 3 단계는 사용자에게 표시되지 않습니다). User1에 대해 2 단계가 완료되기 전에 User2가 자체 가져 오기를 시작합니다. 잠금 메커니즘으로 인해 가져 오기가 즉시 시작되지 않습니다. 주요 관심사는 User2의 1 단계가 User2의 2 단계가 완료되는 즉시 시작되어 User1의 3 단계 전에 표를 지우고 프로세스를 완료 할 수 있다는 것입니다.

세 가지 추가 참고 사항 : ADO를 통해 여기

  1. 클라이언트 측 실행 (안 ADO.NET과 착각하는)
  2. 대량 삽입이
  3. 일부 잠금 메커니즘을 확장을 통해이 일을 안함 옵션을 선택하지 않습니다 가능한 경우 ADO를 통해 1 단계와 2 단계의 프로세스를 단계 2에 포함 할 수 있습니다. 가능하다면 불가능하다는 것을 알고 여기에서도 도움이됩니다.
+0

답변을 업데이트했습니다. – garik

답변

3

전형적인 솔루션은 applocks

sp_getapplock 'importing-ABC', 'Exclusive', 'Session'; 

당신은 규칙에 의해 논리적 자원 (임의의 문자열/이름)과, 잠금이 방법을 통해 획득 한 사용하는 다른 사용자를 시도 동일하게 applock을 얻으려고 시도해야합니다. applock이 개최되는 동안 bcp 명령은 w/o 간섭을 실행할 수 있습니다. 이 경우 이 아닌이 프로토콜을 존중하지 않는 다른 사용자/응용 프로그램 (무지, 악의 또는 어리 석음으로 인해)을 방지합니다.

+0

이것은 흥미로운 옵션처럼 보입니다. User1에 대해 ADO를 통해 GUI에서 sp_getapplock을 호출하고 User1에 의해 다시 릴리스되기 전에 User1에서 코드를 호출하여 코드가 실행되지 않도록 할 수 있습니다. 나는 핵심 단어 'Session'을 알아 차렸다. 확인해야하지만 쉘 호출을 통해 BCP를 실행하고 있습니다. 따라서 BCP는 TRUNCATE 및 sp_modify_temp1_ *을 호출하는 ADO 연결과 다른 세션에 있어야합니다. 이것이 머리 꼭대기에있는 요인인지 아십니까? – user410159

+0

+1 좋은 해결책입니다. – garik

+0

이고르 (Igor)는 테이블 대신에 옵션 # 1과 # 3을 대체하는 것으로 동의합니다. 이것이 의도 한대로 작동하는지 테스트해야 할 것입니다. 모든 옵션이 작동하지만 "답변"이라고 표시합니다.이것은 단지 "새로운 것을 오늘 배웠습니다"라고 말하면서도 # 2와 함께 갈지라도 다른 프로젝트에서 유용하다는 것을 알 수 있습니다. 감사. – user410159

1

1) 제 용액

  • 테이블을
  • 추가 load_session_state 테이블 PK sessionId가, 주 TINYINT (공정 단계 (1), 공정 (2) ... 완료 ...)
  • 을 TEMP1하는 세션 ID 필드를 추가
  • sp_modify_temp1_rows_move_to_production_table은 일부 sessionId 및 State = Done 인 레코드 만 실행합니다. (sp_modify_temp1_rows_move_to_production_table은 SQL 에이전트 작업을 사용하여 비동기 적으로 실행될 수 있습니다.)
  • truncate는 DELETE WHERE SessionId =로 대체해야합니다 (느리지 만 완료해야 함). temp_XXX

2) 제 2 용액

  • CREATE TABLE
  • TABLOCK이 BCP 명령으로부터 제거되어야한다 (이는 동일한 SQL 에이전트 작업이 아니라 생산 레코드를 이동 한 후에 수행 될 수 있음)
  • bcp db.schema1. temp_XXX in import1.TXT -h "TABLOCK"
  • 간부 sp_modify_tempXXX_rows_move_to_production_table @table_name = 'temp_XXX'
  • DROP 표합니다 (@table_name 파라미터 동적 SQL을 사용) temp_XXX는

추가

3) Load_session_state 테이블을 진행보기로 사용하고 프로세스를 잠글 수 있습니다. 그 안에 레코드가 있으면 사용자에게 대기 상태를 알리십시오. 변경없이 이전 솔루션을 사용하십시오. 단지 논리적 잠금으로 테이블 load_session_state를 사용

+0

1과 2를 모두 고려했지만 세션 ID 대신 네트워크 로그인을 사용하고 XXX 대신 로그인을 사용하는 경우가 많습니다. 그러나 나는 희망을 갖고있었습니다. 그러나 어떤 sp_를 통해 User1에게 테이블 잠금을 확장하는 방법이있었습니다. 클라이언트에서 bcp를 어떻게 든 감쌀 수있었습니다. 너의 대답에 감사드립니다. 그런 일이 불가능하다면 나는 기다려보고 # 2로 대답 할 것이다. – user410159

+0

sp_modify_temp1_rows_move_to_production_table은 SQL 에이전트 작업을 사용하여 비동기 적으로 실행할 수 있습니다. – garik

+0

마지막 코멘트가 내 머리 위로 나옵니다. 이게 나에게 무슨 이득이되는지 모르겠다. 또한 ADO에서 sp async를 실행할 수도 있습니다. 작업으로 실행하여 격리 문제를 피하는 방법은 무엇입니까? 어떤 이상한 이유 때문에이 생각을 내 머리 속으로 들려 줘서 SP를 INSTEAD OF, INSERT 트리거로 실행할 수는 있었지만 말이다. BCP를 통해 temp1에 데이터를로드하고, INSTEAD OF는 실제 삽입을 삽입 한 다음 EXEC SQL을 삽입합니까? 그게 고립을 유지해야하지 않습니까? 성능이 떨어지는 지 확실하지 않습니까? 내 환경에서 이러한 시나리오를 테스트하고 타이밍을 완벽하게 만드는 것은 어렵습니다. – user410159