SSDT 및 Visual Studio 2012 데이터베이스 프로젝트로 데이터베이스 배포를 올바르게 관리하는 방법은 무엇입니까?
저는 기존의 소규모 프로젝트에 2012 데이터베이스 프로젝트를 채택하려는 연구 단계에 있습니다. 저는 DBA가 아닌 C # 개발자이므로 모범 사례에 특히 능숙하지 않습니다. 몇 시간 동안 Google과 stackoverflow를 검색했지만 여전히 일부 주요 배포 시나리오를 제대로 처리하는 방법을 모르겠습니다.
1) 여러 개발주기 동안 여러 버전의 데이터베이스를 어떻게 관리합니까? 내 데이터베이스의 v3에 클라이언트가 있고이를 v8로 업그레이드하려면 어떻게 관리합니까? 현재 우리는 제품의 모든 버전에 대해 손으로 만든 스키마 및 데이터 마이그레이션 스크립트를 관리합니다. 이 작업을 별도로 수행해야합니까? 아니면이를 지원하거나 대체하는 새로운 패러다임이 있습니까?
2) 데이터 이동이 필요한 방식으로 스키마가 변경되는 경우이를 처리하는 가장 좋은 방법은 무엇입니까? 데이터를 보존하기 위해 배포 전 스크립트에서 일부 작업이 진행된 다음 배포 후 스크립트가 데이터를 올바른 위치에 다시 배치한다고 가정합니다. 그게 방법입니까, 아니면 더 나은 것이 있습니까?
3) 이러한 새로운 기술을 가장 잘 활용하는 방법에 대한 기타 조언이나 지침도 대단히 감사합니다!
업데이트 : 원래이 질문을 한 이후로 문제에 대한 이해가 조금 증가했으며 실행 가능한 솔루션을 생각해 냈지만 원하는 솔루션이 아닙니다. 내 문제에 대한 표현은 다음과 같습니다.
내가 가진 문제는 순전히 데이터와 관련이 있습니다. 내 애플리케이션의 버전 1에 클라이언트가 있고이를 내 애플리케이션의 버전 5로 업그레이드하려는 경우 데이터베이스에 데이터가 없어도 문제가 없을 것입니다. SSDT가 지능적으로 스키마를 비교하고 데이터베이스를 한 번에 마이그레이션하도록하겠습니다. 불행히도 클라이언트에는 데이터가 있으므로 그렇게 간단하지 않습니다. 내 애플리케이션의 버전 1에서 버전 2, 버전 3 (등)으로의 스키마 변경은 모두 데이터에 영향을줍니다. 현재 데이터 관리 전략을 사용하려면 각 버전 업그레이드 (1에서 2, 2에서 3 등)에 대한 스크립트를 유지해야합니다. 이렇게하면 바로 이동할 데이터 마이그레이션 스크립트가 없기 때문에 응용 프로그램의 버전 1에서 버전 5로 바로 이동할 수 없습니다. 모든 클라이언트에 대한 사용자 정의 업그레이드 스크립트를 작성하거나 모든 버전에서 모든 상위 버전으로 이동하기 위해 업그레이드 스크립트를 관리하는 잠재 고객은 기하 급수적으로 관리 할 수 없습니다. 내가 바랬던 것은 SSDT가 사물의 데이터 측면을 더 쉽게 관리 할 수 있도록하는 일종의 전략이 있다는 것이 었습니다. 아마도 사물의 스키마 측면만큼이나 쉽습니다. 최근 SSDT에 대한 경험으로는 그러한 전략이 존재한다는 희망이 없었지만 다른 방식으로 알아보고 싶습니다.
저는이 작업을 직접 해왔으며 쉽지 않다고 말할 수 있습니다.
첫째, JT의 응답을 처리하기 위해 SSDT에있는 선언적 업데이트 메커니즘을 사용하더라도 "버전"을 무시할 수 없습니다. SSDT는 소스 스키마를 모든 대상 스키마로 이동하는 "매우 괜찮은"작업 (모든 스위치와 문제를 알고있는 경우)을 수행하며 이것이 자체적으로 검증이 필요하지 않다는 것은 사실이지만 관리 방법을 모릅니다. " 데이터 모션 "(적어도 내가 볼 수있는 것은 아닙니다!). 따라서 DBProj와 마찬가지로 사전 / 사후 스크립트에서 자신의 장치에 맡겼습니다. 데이터 모션 스크립트는 알려진 시작 및 종료 스키마 상태에 따라 달라 지므로 DB 버전 관리를 피할 수 없습니다. 따라서 "데이터 모션"스크립트는 스키마의 버전이 지정된 스냅 샷에 적용되어야합니다. 즉, DB를 v1에서 v8로 임의로 업데이트 할 수 없으며 데이터 모션 스크립트 v2에서 v8이 작동 할 것으로 기대할 수 없습니다 (아마도
안타깝게도 SSDT 게시에서이 시나리오를 통합 된 방식으로 처리 할 수있는 메커니즘을 볼 수 없습니다. 즉, 자신 만의 스캐 폴딩을 추가해야합니다.
첫 번째 트릭은 데이터베이스 (및 SSDT 프로젝트) 내에서 버전을 추적하는 것입니다. DBProj에서 트릭을 사용하기 시작했고 SSDT로 가져 왔고 몇 가지 조사를 한 후 다른 사람들도 이것을 사용하고 있음이 밝혀졌습니다. DB 확장 속성을 데이터베이스 자체에 적용하고 ( "BuildVersion"또는 "AppVersion"또는 이와 유사한 이름으로) 버전 값을 적용 할 수 있습니다. 그런 다음 SSDT 프로젝트 자체에서이 확장 속성을 캡처하면 SSDT가이를 스크립트로 추가합니다 (그런 다음 확장 속성을 포함하는 게시 옵션을 확인할 수 있음). 그런 다음 SQLCMD 변수를 사용하여 현재 패스에 적용되는 소스 및 대상 버전을 식별합니다. 소스 (프로젝트 스냅 샷)와 대상 (업데이트 예정인 대상 DB) 사이의 버전 델타를 식별하면 적용해야하는 모든 스냅 샷을 찾을 수 있습니다.SSDT 배포 내부 에 있고 빌드 또는 배포 파이프 라인으로 이동해야 할 것입니다 (우리는 TFS 자동 배포를 사용하고이를 수행하기위한 사용자 지정 작업이 있음).
다음 장애물은 관련 데이터 모션 스크립트와 함께 스키마의 스냅 샷을 유지하는 것입니다. 이 경우 스크립트를 가능한 한 멱등 적으로 만드는 데 도움이됩니다 (즉, 부작용없이 스크립트를 다시 실행할 수 있음). 한 번만 실행해야하는 스크립트에서 안전하게 다시 실행할 수있는 스크립트를 분할하는 데 도움이됩니다. 정적 참조 데이터 (사전 또는 룩업 테이블)로 동일한 작업을 수행합니다. 즉, 참조 데이터를 동기화 상태로 유지하는 MERGE 스크립트 라이브러리 (테이블 당 하나)가 있으며 이러한 스크립트는 게시물에 포함됩니다. -deployment 스크립트 (SQLCMD : r 명령을 통해). 여기서주의해야 할 중요한 것은 당신이 있다는 것입니다 해야이러한 참조 테이블에 서로에 대한 FK 참조가있는 경우 올바른 순서로 실행하십시오. 기본 배포 후 스크립트에 순서대로 포함하고 이러한 스크립트를 생성하는 도구를 만드는 데 도움이됩니다. 또한 종속성 순서도 해결됩니다. 정적 참조 데이터의 현재 상태를 캡처하기 위해 "버전"이 끝날 때이 생성 도구를 실행합니다. 다른 모든 데이터 모션 스크립트는 기본적으로 특수한 경우이며 대부분 일회용 일 것입니다. 이 경우 두 가지 중 하나를 수행 할 수 있습니다. db 빌드 / 앱 버전에 대해 IF 문을 사용하거나 각 스냅 샷 패키지를 생성 한 후 1 회 스크립트를 지울 수 있습니다.
SSDT는 FK 검사 제약 조건을 비활성화하고 배포 후 스크립트가 실행 된 후에 만 다시 활성화한다는 점을 기억하는 것이 좋습니다. 예를 들어 널이 아닌 새 필드를 채울 수있는 기회를 제공합니다 (그런데이 작업을 수행하려면 널이 아닌 열에 대해 임시 "스마트"기본값을 생성하는 옵션을 활성화해야합니다). 그러나 FK 검사 제약 조건은 스키마 변경으로 인해 SSDT가 다시 만드는 테이블에 대해서만 비활성화됩니다. 다른 경우에는 검사 제약 조건 불만 사항을 방지하기 위해 데이터 모션 스크립트가 적절한 순서로 실행되도록 할 책임이 있습니다 (또는 스크립트에서 수동으로 비활성화 / 재 활성화).
DACPAC은 본질적으로 스냅 샷이기 때문에 DACPAC이 도움이 될 수 있습니다. 여기에는 스키마 (프로젝트의 빌드 출력과 유사)를 설명하는 여러 XML 파일이 포함되지만 생성하는 순간 고정됩니다. 그런 다음 SQLPACKAGE.EXE 또는 배포 공급자를 사용하여 해당 패키지 스냅 숏을 게시 할 수 있습니다. DACPAC 버전 관리는 "등록 된"데이터 앱에 더 묶여 있기 때문에 우리는 자체 버전 관리 체계를 고수하고 있지만 DACPAC 파일 이름에 자체 버전 정보를 넣습니다.
좀 더 결정적이고 설명 할 수있는 예시가 있었으면 좋겠지 만 여기서도 문제를 해결하고 있습니다.
SSDT에 대해 정말 짜증나는 점은 DBProj와 달리 현재 확장 할 수 없다는 것입니다. 많은 다른 점에서 DBProj보다 훨씬 더 나은 작업을 수행하지만 문제를 해결하는 사전 / 사후 스크립트 내에서 몇 가지 방법을 찾을 수없는 경우 기본 동작을 재정의 할 수 없습니다. 지금 해결하려는 문제 중 하나는 업데이트 용 테이블 (CCDR)을 다시 만드는 기본 방법이 수천만 개의 레코드가있을 때 실제로 악취가 나는 것입니다.
-업데이트 : 한동안이 게시물을 보지 못했지만 최근에 활성화 되었기 때문에 몇 가지 중요한 메모를 추가 할 것이라고 생각했습니다. VS2012를 사용하는 경우 SSDT의 2013 년 6 월 릴리스에는 이제 데이터가 있습니다. 비교 도구가 기본 제공되며 확장 성 포인트도 제공합니다. 즉, 이제 프로젝트에 대해 빌드 기여자 및 배포 계획 수정자를 포함 할 수 있습니다.
나는 주제에 대해 더 이상 유용한 정보를 찾지 못했지만 도구에 대해 알아보고, 손질하고, 놀면서 시간을 보냈으며, 내 질문에 대해 수용 가능한 답변을 생각 해낸 것 같습니다. 이것이 반드시 최선의 답변은 아닙니다. 이러한 시나리오를 더 잘 지원할 수있는 다른 메커니즘이나 모범 사례가 있는지는 아직 모르겠지만 다음은 제가 생각 해낸 것입니다.
주어진 데이터베이스 버전에 대한 사전 및 사후 배포 스크립트는 이전 버전의 데이터를 마이그레이션하는 데만 사용됩니다. 모든 개발주기가 시작될 때 스크립트가 정리되고 개발이 진행됨에 따라 이전 버전에서 새 버전으로 데이터를 안전하게 마이그레이션하는 데 필요한 모든 SQL로 구체화됩니다. 여기서 한 가지 예외는 데이터베이스의 정적 데이터입니다. 이 데이터는 디자인 타임에 알려져 있으며 T-SQL MERGE 문 형식으로 배포 후 스크립트에 영구적으로 존재합니다. 이렇게하면 최신 게시 스크립트 만 사용하여 모든 버전의 데이터베이스를 새 환경에 배포 할 수 있습니다. 모든 개발주기가 끝날 때 게시 스크립트가 이전 버전에서 새 버전으로 생성됩니다. 이 스크립트에는 스키마를 마이그레이션하기 위해 생성 된 SQL과 손으로 만든 배포 스크립트가 포함됩니다. 예, 게시 도구가 데이터베이스에 대해 직접 사용될 수 있다는 것을 알고 있지만 이는 고객에게 좋은 옵션이 아닙니다. dacpac 파일도 알고 있지만 사용 방법을 잘 모르겠습니다. 생성 된 게시 스크립트는 프로덕션 업그레이드에 대해 제가 아는 가장 좋은 옵션 인 것 같습니다.
So to answer my scenarios:
1) To upgrade a database from v3 to v8, I would have to execute the generated publish script for v4, then for v5, then for v6, etc. This is very similar to how we do it now. It's well understood and Database Projects seem to make creating/maintaining these scripts much easier.
2) When the schema changes from underneath data, the Pre- and Post-Deploy scripts are used to migrate the data to where it needs to go for the new version. Affected data is essentially backed-up in the Pre-Deploy script and put back into place in the Post-Deploy script.
3) I'm still looking for advice on how best to work with these tools in these scenarios and others. If I got anything wrong here, or if there are any other gotchas I should be aware of, please let me know! Thanks!
In my experience of using SSDT the notion of version numbers (i.e. v1, v2...vX etc...) for databases kinda goes away. This is because SSDT offers a development paradigm known as declarative database development which loosely means that you tell SSDT what state you want your schema to be in and then let SSDT take responsibility for getting it into that state by comparing against what you already have. In this paradigm the notion of deploying v4 then v5 etc.... goes away.
Your pre and post deployment scripts, as you correctly state, exist for the purposes of managing data.
Hope that helps.
JT
I just wanted to say that this thread so far has been excellent.
I have been wrestling with the exact same concerns and am attempting to tackle this problem in our organization, on a fairly large legacy application. We've begun the process of moving toward SSDT (on a TFS branch) but are at the point where we really need to understand the deployment process, and managing custom migrations, and reference/lookup data, along the way.
To complicate things further, our application is one code-base but can be customized per 'customer', so we have about 190 databases we are dealing with, for this one project, not just 3 or so as is probably normal. We do deployments all the time and even setup new customers fairly often. We rely heavily on PowerShell now with old-school incremental release scripts (and associated scripts to create a new customer at that version). I plan to contribute once we figure this all out but please share whatever else you've learned. I do believe we will end up maintaining custom release scripts per version, but we'll see. The idea about maintaining each script within the project, and including a From and To SqlCmd variable is very interesting. If we did that, we would probably prune along the way, physically deleting the really old upgrade scripts once everybody was past that version.
BTW - Side note - On the topic of minimizing waste, we also just spent a bunch of time figuring out how to automate the enforcement of proper naming/data type conventions for columns, as well as automatic generation for all primary and foreign keys, based on naming conventions, as well as index and check constraints etc. The hardest part was dealing with the 'deviants' that didn't follow the rules. Maybe I'll share that too one day if anyone is interested, but for now, I need to pursue this deployment, migration, and reference data story heavily. Thanks again. It's like you guys were speaking exactly what was in my head and looking for this morning.
'development' 카테고리의 다른 글
추상 클래스에서 구체적인 클래스 이름 가져 오기 (0) | 2020.12.05 |
---|---|
RejectedExecutionException의 원인은 무엇입니까? (0) | 2020.12.05 |
URL을 작성하는 방법은 무엇입니까? (0) | 2020.12.05 |
React : React가 렌더링 한 DOM을 얼마나 조작 할 수 있습니까? (0) | 2020.12.05 |
소멸자에서 dispose (false)를 호출하는 이유는 무엇입니까? (0) | 2020.12.05 |