SQL Serverのインプレースアップグレードは、以前と同じように不適切にアドバイスされていますか?


78

私はSQL Server 6.5以降、SQL Serverのオンとオフを操作してきました。私の頭に残っている古いアドバイスは、インプレースアップグレードを行うことではありませんでした。

現在、2008 R2 DEVおよびTESTシステムをSQL Server 2012にアップグレードしていますが、同じハードウェアを使用する必要があります。Reporting Servicesの構成を復元する必要がないという考えは非常に魅力的であり、実際には時間的に賢明です。関係する分析サービスや異常なもの、非標準のものはありません。データベースエンジンとレポートサービスのみがインストールされます。

インプレースアップグレードで深刻な問題を経験した人はいますか?または、インプレースアップグレードに関する自分の立場を再評価する必要がありますか?


Reporting Servicesをインストールした1台のサーバーでインプレースアップグレードを行うことにしました。私が遭遇した唯一の問題は、ネイティブクライアント11でSSMSのインポートエクスポートツールを使用しようとしたことです。認識されないデータ型に関するエラーで変換を試みても失敗しました。私が使用した回避策は、パッケージを保存し、SQL Data Tools(BIDS replacement)で実行することで、正常に機能しました。これは、SSIS 2008の構成ファイルが上書きされていないことに関係していると思います。後になって、ネイティブクライアントを単に10に戻すことができるかもしれません
。– DamagedGoods

回答:


92

本当に短い答え -インプレースは大丈夫です。その後、構成を確認し、SQL Server 2012のベストプラクティスを実装できます。

SQL Serverのアップグレード/移行に関する長い回答

したがって、これは意見の問題であり、必ずしも間違った答えや正しい答えがあるわけではありませんが、多くの理由から、インプレースよりも移行スタイルのアップグレードを好みます。言われていること-さまざまな理由で私のクライアントの一部は、インプレースを実行する以外に選択肢がなく、実際にはSQL Server 2005以降、インプレースアップグレードは以前ほど悪くありませんでした。

インプレースアップグレードへの移行を好む理由

  • より簡単なロールバック -何か問題が発生した場合は、「アップグレードを中止しました。これを解決する間、接続文字列を古いサーバーに変更してください」と簡単にロールバックできます。インプレースでは、それを修正するか、ダウンしています。
  • ハードウェアの更新 -ハードウェアは急速に変化します。4年前は自社に適していたハードウェアに簡単にこだわることができますが、インプレースアップグレードを行うと、現在および今後4年間は適切ではありません。とにかく、新しいハードウェアについては、何らかの時点で移行を行う必要があります。
  • Feel Better-もちろん...これは主観的ですが、新しいOSインストール、仕事の前の人(または自分が知っていることを知る前の人)からのクモの巣のない新しいSQLインストールで始めることを知っているのは良い気分です今日)それはおそらくあなたに将来頭痛を引き起こす可能性があります。
  • 新しいOS-移行すると、最新かつ最高のOSを使用していない場合に、新しいOSバージョンで開始する機会が与えられます。
  • テストできます-SQLをインストールし、データベースと使用状況でクラウド化する前に、新しいマシンでベースラインのセットを取得したいですか?今すぐできます。
  • ベストプラクティスを忍び込むほうが簡単な場合があります-SQL Serverサービスアカウントはローカル管理者である可能性があります。たぶん、ビルトイン管理者はSAサーバーの役割にあります。たぶん、前にそれを機能させるために、物事が一緒にハッキングされたのかもしれません。そのすべてを修正して、新たに開始できます。
  • 無料のテスト環境と余分な睡眠 -この新しい環境をライブにする実際のカットオーバー日の前に作業できる環境があることは大きな利点です。新しい環境への移行を行うと、実際のカットオーバー日のかなり前に、営業時間中にそれを構築し、事前に多くの方法でテストできます。すべてのアプリケーションおよびシステムで完全なリグレッションテストを数日間実行し、実際に最終セットの復元/アタッチを行い、すべてのアプリケーションと新しい環境へのアクセスをカットオーバーする前に、非常に安心できます。
  • 一度にすべてを行う必要はありません -私が遭遇する非常に一般的な状況は、ごく少数のインスタンスに統合しようとしている環境です。おそらくバージョンごとに1つ、おそらく「層」とバージョンごとに1つです。これらのプロジェクトの多くは、テスト、プロジェクト計画、ベンダー認定の適時性に基づいて、さまざまなアプリケーションやデータベースのタイムラインが異なります。移行を行うということは、何らかの理由で移動できないデータベースの要求を処理する準備が整ったときに、準備が整ったデータベースを移動できることを意味します。

気を付けてください、これは移行として行う必要があると言っているのではありません。インプレースは機能します。予算内で新しいハードウェアを購入する予定がなく、このアップグレードでそれができない場合は適切に機能します。アップグレードプロセスでのサポートは6.5日よりもはるかに優れているため、これを行うことで悪い立場に陥ることはありません。

開発/テストのインプレース実行を計画しているが、本番環境の移行を実行する場合は、本番の前に少なくとも1つの移行を実行することを検討してください。これにより、事前にチェックリストを作成し、考えていない潜在的な問題に対処できます。

移行のためのアタッチ/デタッチとバックアップ/リストア

移行アプローチを採用することに決めた場合、まだ議論の余地があるもう1つの決定があり、それがデータベースを新しい環境に移動する方法です。古いサーバーからデータベースをデタッチして新しいサーバーにアタッチするか、バックアップしてそこに復元することができます。

バックアップ/復元が好きです。デタッチ/アタッチについて聞いた最大の利点は、時間を節約できることです。私にとっては、いくつかの理由でバックアップ/復元が成功します:

  • 古いアクセス可能なままにする -これにより、ソースサーバー上にアクセス可能なデータベースを保持できます。デタッチ/アタッチも同じように実行する必要がありますが、いくつかの手順が必要であり、デタッチ/アタッチでこれを複雑にする可能性がある人為的なエラーの余地があります。
  • バックアップがあることを保証します -データベースをデタッチから取得してバックアップ手順を忘れる可能性がある代わりに、そのバックアップを取得したことを確認しました。
  • 人為的エラー -間違ったファイルを削除したり、送信先を忘れたり、手順を台無しにしたりすると、データベースのデータやログファイルを移動することで大きなリスクが生じます。これで、カットする代わりにコピーすることでこれを緩和できます(デタッチする場合は、カットアンドペーストの習慣から抜け出す必要があります)が、混乱する可能性があります。SQL Serverはこれらのファイルをロックしなくなりました。ファイルを誤って削除してしまうと、危険にさらされてしまいます。
  • それは本当にないことを遅く、バックアップを取って、それをコピーするにはもう少し時間があるが、私がそれのために余分なリスクを支払うことを喜んでいることをそれほどではありません- 。実際、フルリカバリモデルとログバックアップを使用すると、「移行アプローチを高速化する方法」で説明するように、カットオーバーのダウンタイムをさらに短縮できます。

バックアップ/復元を行うことにした場合-つまり、古いソースデータベースは引き続きオンラインになります。バックアップを取った後、そのデータベースをオフラインにするのが好きです。セキュリティ、ジョブ、リンクサーバー、証明書、データベースメール設定、およびその他のインスタンス全体の情報をスクリプト化した後、さらに一歩進んでSQLインスタンス全体をオフラインにすることがあります。これにより、テスト中に誰かが「すべてが素晴らしく見える」と言う問題を回避できます。1日か2日後に、古いサーバー上の古いデータベースと通信していることを認識します。それらのデータベースをオフラインにするか、インスタンス全体をオフラインにすることで、これらの誤検知や混乱を防ぐことができます。

移行アプローチを高速化する方法

完全復旧モデルを利用することにより、ダウンタイムがほとんどない忙しい実稼働環境で、古い環境から新しい環境へのカットオーバーに必要なダウンタイムを最小限に抑えることができます。基本的に-最新の完全バックアップ、差分バックアップ、および既に取得したログバックアップを指定して、移行先の環境をステージングします。NORECOVERY最後のカットオーバーで必要なのは、まだ復元されていないログバックアップを復元することです。を指定して復元する最終ログバックアップWITH RECOVERY。このように、大規模なデータベースの場合、完全、差分、およびほとんどのログリストアのコストをダウンタイムウィンドウの前に支払うことで、実際のカットオーバーダウンタイムウィンドウを大幅に最小化できます。コメントでこれを指摘してくれたTaoに感謝します!

インプレースアップグレードをより安全にする方法

インプレースアプローチを選択する際に、経験と結果を改善するためにできるいくつかのこと。

  • バックアップ -環境のすべてのユーザーデータベースおよびシステムデータベースの適切なバックアップを事前に取得し、それらが適切であることを確認します(私は妄想します。 。しかし、災害が発生した場合は自分自身に感謝するかもしれません。)その環境でのSQLおよびOSのインストールに関する構成情報をスクリプト化します。
  • 始める前に十分にテストしてください-良好な環境と良好なデータベースがあることを確認してください。エラーログを確認したり、DBCC CHECKDBを定期的に実行するなどの作業を行う必要がありますが、インプレースアップグレードを実行する前に開始するのが最適です。事前に問題を修正してください。
  • OSの正常性を確認する-SQLが正常であることを確認するだけでなく、サーバーが正常であることを確認してください。システムまたはアプリケーションのエラーイベントログに重大なエラーがありますか?あなたの空き容量はどうですか?
  • 最悪の事態に備えて -しばらく前にブログ記事シリーズで、失敗の準備をしていないのなら、実際失敗の準備ているという前提で行った..私はまだ信じています。だから、あなたが持っているかもしれない問題を考え、事前にそれに応じてそれらに対処します。「失敗」の考え方に身を任せてください。そうしないと思いつかないことを考えるでしょう。

アップグレードまたは移行チェックリストの重要性

アップグレード(インプレースまたは移行)を行うことにした場合は、チェックリストを作成し、各環境でこのチェックリストを使用することを真剣に検討する必要があります。このチェックリストには、少なくとも次のものではなく、多くのものを含める必要があります。

  1. 開始時 -テストアップグレードの実行、最新のデータベース互換性レベルでのアプリケーションのテストなどを実行し、SQL Server Upgrade Advisorなどのツールを事前に実行して、SQLを実行する前に完了する必要のあるタスクの種類を確認しますサーバーのアップグレードまたは移行。
  2. 事前手順 -クリーンアップ、OSタスク、事前のパッチ適用、アップグレードのためのアプリケーションの準備(クリーンシャットダウン、接続文字列作業)、バックアップなど
  3. アップグレード/移行手順 -アップグレードまたは移行を成功させるために必要なすべてを正しい順序で実行します。データベースへの互換モードの変更など、インストール、変更(またはテストとアプローチに応じて変更しない)
  4. 移行/アップグレード後の手順 -さまざまなテスト、新しいバージョンまたは新しいサーバー構成オプションの投稿、ベストプラクティスの実装、セキュリティの変更など。
  5. ロールバック手順 -途中でロールバック手順とマイルストーンが必要です。ここまで来てこれが起こったら、どうしますか?「フルロールバックを行う」条件とは何ですか?そして、そのロールバックをどのように行いますか(逆接続文字列の変更、設定の変更、古いバージョンへの戻り、適切な場合は再インストール、移行の場合は古いサーバーへの戻りなど)。

そして、本番環境のアップグレードを行う人に、本番環境以外の環境、特に可能であれば本番環境に近いもの(私が言うように「製品の南」)のチェックリストに従い、問題やポイントを書き留めます。チェックリストが不足していたため、チェックリストから転用したり、即興で演奏する必要がありました。次に、変更をマージして、生産の変更を楽しんでください。

移行後またはアップグレード後、移行前に十分にテストすることの重要性を強調することはできません。アップグレードの最中にロールバックを決定するのは簡単です-特に移行中は。不快なものがある場合は、ロールバックして、移行の最中に効果的かつ確実にトラブルシューティングできない場合にそれを見つけ出します。この新しい環境で稼働し、ユーザーが接続すると、ロールバックは困難なタスクになります。SQL Serverデータベースを以前のバージョンに復元することはできません。つまり、手作業とデータの移行を意味します。私はいつも古い環境を殺すために数週間待ちますが、あなたの生きているユーザーが新しい環境に触れる前にすべての問題を見つけることでその古い環境を必要としないようにできる限りのことをすべきです。できればアップグレード/移行を開始する前に。

SQL Server Reporting Servicesの移行/アップグレードに関する簡単な注意 SSRSインストールの移行は、多くの人が考える非常に困難な作業ではありません。このtechnet / booksオンライン記事は、実際には非常に便利です。その記事で最も重要な注意点の1つは、特にスケジュールされたレポートの電子メール受信者の電子メールアドレス、多数の接続の接続情報などの多くの保存された機密情報がある場合は「暗号化キーのバックアップ」ですしばらく前から私のクライアントの一人にそれがどれほど重要かを尋ねることができます。私はそのステップアップを台無しにして、レポートスケジュールと接続文字列のアクセス許可を変更するのにかなりの時間を費やしたため、彼らは知っています。


14

私の経験では、以前と同じ意思決定プロセスを行う必要があります。知る限り、MS SQL Server製品自体にはSQL Serverのインストールに関する「世界の変化」はなく、数百万行のコードを含むソフトウェアを展開するときに発生する可能性のある問題がありました。何か悪いことが起こる可能性があり、今は「ROLLBACK」オプションがありません。

ただし、他の選択肢があります。システムのスナップショットを作成し、他の場所に復元し、アップグレードを実行して、何が起こるかを確認できます。このテストは多くの快適さを提供するはずですが、prodボックスで問題が発生しないことを完全に保証するものではありません。ただし、これはSQL 6.5で使用できなかったオプションです。

最悪のシナリオを想定しています。インプレースアップグレードを行うと、それは惨めに失敗します。その後、RTOとRCO内でこれから回復する必要があります。ビジネスはリスクを理解しており、リスクを軽減するための計画はありますか?

これでビジネスがうまくいかない場合は、しないでください、それは私のアドバイスになります。


2

サーバーを仮想環境で実行している場合、クローンでスナップショットを実行してから、インプレースアップグレードを適用し、インスタンスをテストして、アップグレードが成功したことを確認できます。動作する場合は、スナップショットを適用し、クローンを運用サーバーにすることができます。うまくいかない場合は、スナップショットを削除してアップグレード前のイメージに戻って再試行するか、クローンを削除して完全に移行することができます。


1
ストレージも仮想化され、スナップショットの一部である場合のみ。ストレージは、直接スナップショットが復元されたとき、それは「ロールバック」されることはありませんVM ...に接続されている場合
レムスRusanu

1

ハードウェアへの多額の投資のため、現在のSQL Serverバージョン(2012、3サーバー、22インスタンス、約300データベース)を維持しながらOSのみをアップグレードする必要がありました。ミラーリングなどの複雑な設定は不要

SQL Serverはアップグレードされていないため、この例は質問と完全には一致しません。示されている手順は実際のインプレース移行よりも実際に単純であるため、これはまだ良い答えだと思います。

概要:主に予防策として、フルバックアップを行うために外部ドライブが接続されました。モデルとmsdbのみが外部ドライブから実際に復元されます。ldf / mdfは、デタッチ/アタッチのために残されました。一部のローカルアカウントは、DB内で参照されました。OSで再作成された後、DB内の参照が再作成されました(SIDが変更される可能性があるため)。

それから私達のために働いたステップはここにあった:

1)手順12(サーバーの役割)および18〜23で復元されるサーバーレベルの設定に注意してください。

2)SQL Server 2012をSP3にパッチします(システムdbを復元する場合は一貫性が必要です)。

3)各インスタンスでバージョンが一致することを確認します。「@@ versionを選択」

4)このスクリプトを実行して、これらの6つのスクリプトを生成します。Redgate SQL Multiscriptは、多数のインスタンスがある場合(ツール->オプション=>行の長さを最大(8192)に調整し、テキスト出力を使用する場合)で時間を大幅に節約できます。

  • バックアップ
  • 戻す
  • 切り離す
  • 添付
  • ログインを再作成する
  • ユーザーをログインに再リンクする

    -- (1) BACKUP / (2) RESTORE
    --    
    --*** SET THESE to external drive location
    --*** and create the Destination Directories
    declare 
        @backupInstanceDir  varchar(300) = 'F:\ExternalDriveBackups\' + replace(@@servername, '\', '_'),
        @dateSuffix         varchar(100) = '2015-12-14'; 
    
    if (object_id('tempdb..DatabaseStatus') is not null)
    drop table #DAtabseSTatus;
    
    select 
        d.name DbName, 
        d.state_desc DbState,
        d.user_access_desc UserMode,
        convert(bit, (d.is_read_only * -1 + 1)) as IsWritable,
        d.is_trustworthy_on as IsTrustWorthy,
        d.is_in_standby IsInStandby,
        d.recovery_model_desc RecoveryModel,
        suser_sname(d.owner_sid) as Owner,
        convert(bit, 
            case when d.database_id <= 4 or d.is_distributor = 1
                then 1
                else 0
            end) as IsSystemDb,
        mf.type_desc as FileType,
        mf.name FileName,
        mf.state FileState,
        mf.state_desc FileStatDesc,
        mf.physical_name PhysicalName,
        mf.type as FileTypeId    
    into #DatabaseStatus
    from
        sys.master_files AS mf
    join sys.databases AS d
    ON  mf.database_id = d.database_id
    where
        1=1
    order by
        d.name,
        mf.physical_name;
    
    if object_id('tempdb..#sqlOut') is not null
        drop table #sqlOutBU
    
    if object_id('tempdb..#sqlOut') is not null
        drop table #sqlOutRE
    
    create table #sqlOutBU
    (
        Command nvarchar(max) not null,
        Row int identity(1,1) not null primary key
    );
    
    create table #sqlOutRE
    (
        Command nvarchar(max) not null,
        Row int identity(1,1) not null primary key
    );
    
    insert into #sqlOutBU select char(10) + '-- BACKUP SCRIPT' + char(10);
    insert into #sqlOutRE select char(10) + '-- RESTORE SCRIPT' + char(10);
    
    
    insert into #sqlOutBU select char(10) + char(10) + '/* ---------------------------------------------------------------------------------------------' + char(10) + 
    'ServerName: ' + @@servername + char(10) + 'ServiceName: ' + @@servicename + char(10) + 'Version: ' + @@version + 
    '--------------------------------------------------------------------------------------------- */';
    
    insert into #sqlOutRE select char(10) + char(10) + '/* ---------------------------------------------------------------------------------------------' + char(10) + 
    'ServerName: ' + @@servername + char(10) + 'ServiceName: ' + @@servicename + char(10) + 'Version: ' + @@version + 
    '--------------------------------------------------------------------------------------------- */';        
    
    PRINT '--Script for Backing up all DBs in a SQL Server Instance to a specific location' 
    
    SET nocount ON 
    
    insert into #sqlOutBU select char(10) + 
    '--' + char(10) + '-- BACKUP ' + @@servername + '--' + char(10) + 
    'use [Master]; set deadlock_priority high;' + char(10);
    
    insert into #sqlOutRE select '
    -- RESTORE
    --
    -- BE SURE TO BACKUP SYSTEM DBS TO AN ALTERNATE LOCATION JUST BEFORE RESTORING!
    --
    use [Master]; set deadlock_priority high;' + char(10);
    
    DECLARE @dbname nvarchar(128) 
    declare dblist_cursor cursor fast_forward for 
    select [name] from master.sys.databases where [name] != 'tempdb'
    order by iif(database_id <= 4, '0', '1') + [name]
    
    open dblist_cursor 
    fetch next from dblist_cursor into @dbname 
    
    while @@fetch_status = 0 
    begin 
    
        declare @bak nvarchar(300) = @backupInstanceDir + '\' + @dbname + '_' + @dateSuffix + '.bak';
    
        insert into #sqlOutBU select char(10) + 'backup database [' + @dbname + '] to disk = ''' + @bak + ''' WITH COPY_ONLY, NOFORMAT, NOINIT, ' + char(10) + 
            'NAME = N''' + @dbName + '-Full'', SKIP, NOREWIND, NOUNLOAD, COMPRESSION, STATS = 25;';
    
        insert into #sqlOutRE select 'restore database [' + @dbName + '] from disk = ''' + @bak + ''' WITH FILE = 1,' + char(10) +
        (
            select '    move ''' + FileName + ''' to ''' + PhysicalName + '''' From #DatabaseStatus
            where FileType = 'Rows' and DbName = @dbName
        ) + ',' + char(10) +
        (
            select '    move ''' + FileName + ''' to ''' + PhysicalName + '''' From #DatabaseStatus
            where FileType = 'Log' and DbName = @dbName
        ) + ',' + char(10) +
        '    NOUNLOAD, REPLACE, STATS = 25;' + char(10);               
    
        fetch next from dblist_cursor into @dbname 
    end 
    
    close dblist_cursor 
    deallocate dblist_cursor 
    
    insert into #sqlOutBU select char(10) + 'go' + char(10);
    insert into #sqlOutRE select char(10) + 'go' + char(10);
    
    select Command from #sqlOutBU order by Row; -- BACKUP SCRIPT
    select Command from #sqlOutRE order by Row; -- RESTORE SCRIPT
    
    go
    
    
    
    --
    -- (3) DETACH  -  Org Author: Artemakis Artemiou
    --      
    
    if object_id('tempdb..#sqlOutDT') is not null
        drop table #sqlOutDT
    
    create table #sqlOutDT
    (
        Command nvarchar(max) not null,
        Row int identity(1,1) not null primary key
    );
    
    insert into #sqlOutDT select char(10) + '-- DETACH all DBs from a SQL Server Instance' + char(10);      
    
    insert into #sqlOutDT select char(10) + char(10) + '/* ---------------------------------------------------------------------------------------------' + char(10) + 
    'ServerName: ' + @@servername + char(10) + 'ServiceName: ' + @@servicename + char(10) + 'Version: ' + @@version + 
    '--------------------------------------------------------------------------------------------- */';
    
    SET nocount ON 
    
    insert into #sqlOutDT select char(10) + '--' + char(10) + '-- DETACH ' + @@servername + char(10) + '--' + char(10) + '
    use MAster; set deadlock_priority high;' + char(10) + char(10);
    
    DECLARE @dbname nvarchar(128) 
    DECLARE dblist_cursor CURSOR fast_forward FOR 
    SELECT [name] 
    FROM   master.sys.databases 
    WHERE  database_id > 4 
    
    OPEN dblist_cursor 
    FETCH next FROM dblist_cursor INTO @dbname 
    
    WHILE @@FETCH_STATUS = 0 
    BEGIN 
        insert into #sqlOutDT select
        'alter database ' + @dbname + ' set single_user with rollback immediate;' + char(10) +
        'EXEC sp_detach_db ''' + @dbname + ''', ''true'';' + char(10);
        FETCH next FROM dblist_cursor INTO @dbname 
    END 
    
    CLOSE dblist_cursor 
    DEALLOCATE dblist_cursor 
    
    insert into #sqlOutDT select char(10) + 'go' + char(10);
    select Command from #sqlOutDT order by Row;
    
    go
    
    
    
    --
    -- (4) ATTACH  -  Org Author: Artemakis Artemiou
    --    
    
    if object_id('tempdb..#sqlOut') is not null
        drop table #sqlOutAT
    
    create table #sqlOutAT
    (
        Command nvarchar(max) not null,
        Row int identity(1,1) not null primary key
    );
    
    insert into #sqlOutAT select char(10) + '-- ATTACH ALL DBs to a SQL Server Instance' + char(10);
    
    insert into #sqlOutAT select char(10) + char(10) + '/* ---------------------------------------------------------------------------------------------' + char(10) + 
    'ServerName: ' + @@servername + char(10) + 'ServiceName: ' + @@servicename + char(10) + 'Version: ' + @@version + 
    '--------------------------------------------------------------------------------------------- */';
    
    SET NOCOUNT ON
    
    insert into #sqlOutAT select char(10) + '--' + char(10) + '-- ATTACH ' + @@servername + char(10) + '--' + char(10) + 
    'use MAster;' + char(10) + char(10);
    
    DECLARE @dbname nvarchar(128);
    
    DECLARE DBList_cursor CURSOR fast_forward FOR 
    select [name] from master.sys.databases where database_id > 4
    order by name;
    
    OPEN DBList_cursor
    
    FETCH NEXT FROM DBList_cursor 
    INTO @dbname
    
    WHILE @@FETCH_STATUS = 0
    BEGIN
    
    declare @attach_TSQL_script varchar(max)
    set @attach_TSQL_script=''
    set @attach_TSQL_script=@attach_TSQL_script+'CREATE DATABASE ' + @dbname +' ON ' 
    
    declare @tsql varchar(max),@filename varchar(max)
    set @tsql='DECLARE DBFiles_cursor CURSOR FOR select [filename] from '+ @dbname + '.sys.sysfiles'
    
    execute (@tsql) 
    
    PRINT '--'+@dbname 
    
    OPEN DBFiles_cursor
    FETCH NEXT FROM DBFiles_cursor INTO @filename
    
    WHILE @@FETCH_STATUS = 0
    BEGIN   
    set @attach_TSQL_script=@attach_TSQL_script+ char(10)+'    (FILENAME = '''+ @filename +'''),' 
    FETCH NEXT FROM DBFiles_cursor INTO @filename
    END
    
    set @attach_TSQL_script=SUBSTRING(@attach_TSQL_script,0,len(@attach_TSQL_script))
    set @attach_TSQL_script=@attach_TSQL_script+ char(10) +'    FOR ATTACH;';
    
    insert into #sqlOutAT select @attach_TSQL_script + char(10);
    
    PRINT @attach_TSQL_script 
    PRINT ''
    
    CLOSE DBFiles_cursor
    DEALLOCATE DBFiles_cursor
    
    FETCH NEXT FROM DBList_cursor 
    INTO @dbname
    
    END 
    
    CLOSE DBList_cursor
    DEALLOCATE DBList_cursor
    
    insert into #sqlOutAT select char(10) + 'go' + char(10);
    select Command from #sqlOutAT order by Row;
    go
    
    
    
    --
    -- (5) GENERATE A 'RE-CREATE LOGINS' SCRIPT
    --
    -- This script was modified from a version that was designed to copy from one server to another:
    --      http://stackoverflow.com/a/5983773/538763
    --
    
    
    USE [master]
    
    if object_id('tempdb..#sqlOut') is not null
    drop table #sqlOut;
    
    create table #sqlOut
    (
    Command nvarchar(max) not null,
    Row int identity(1,1) not null primary key
    );
    
    insert into #sqlOut select char(10) + '-- RECREATE LOGINS' + char(10);
    
    
    insert into #sqlOut select char(10) + char(10) + '/* ---------------------------------------------------------------------------------------------' + char(10) + 
    'ServerName: ' + @@servername + char(10) + 'ServiceName: ' + @@servicename + char(10) + 'Version: ' + @@version + 
    '--------------------------------------------------------------------------------------------- */';
    
    insert into #sqlOut select 'use Master;' + char(10);
    go
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    declare @Debug bit = 0;
    declare @PartnerServer varchar(100) = @@SERVICENAME;  -- use current server before it is shutdown (disabled below)
    
    declare
        @MaxID int,
        @CurrID int,
        @SQL nvarchar(max),
        @LoginName sysname,
        @IsDisabled int,
        @Type char(1),
        @SID varbinary(85),
        @SIDString nvarchar(100),
        @PasswordHash varbinary(256),
        @PasswordHashString nvarchar(300),
        @RoleName sysname,
        @Machine sysname,
        @PermState nvarchar(60),
        @PermName sysname,
        @Class tinyint,
        @MajorID int,
        @ErrNumber int,
        @ErrSeverity int,
        @ErrState int,
        @ErrProcedure sysname,
        @ErrLine int,
        @ErrMsg nvarchar(2048);
    
    declare @Logins Table (LoginID int identity(1, 1) not null primary key,
                        [Name] sysname not null,
                        [SID] varbinary(85) not null,
                        IsDisabled int not null,
                        [Type] char(1) not null,
                        PasswordHash varbinary(256) null)
    declare @Roles Table (RoleID int identity(1, 1) not null primary key,
                    RoleName sysname not null,
                    LoginName sysname not null)
    declare @Perms Table (PermID int identity(1, 1) not null primary key,
                    LoginName sysname not null,
                    PermState nvarchar(60) not null,
                    PermName sysname not null,
                    Class tinyint not null,
                    ClassDesc nvarchar(60) not null,
                    MajorID int not null,
                    SubLoginName sysname null,
                    SubEndPointName sysname null)
    
    Set NoCount On;
    
    If CharIndex('\', @PartnerServer) > 0
    Begin
    Set @Machine = LEFT(@PartnerServer, CharIndex('\', @PartnerServer) - 1);
    End
    Else
    Begin
    Set @Machine = @PartnerServer;
    End
    
    -- Get all Windows logins from principal server
    Set @SQL = 'Select P.name, P.sid, P.is_disabled, P.type, L.password_hash' + CHAR(10) +
        'From ' /*+ QUOTENAME(@PartnerServer) + '.*/ + 'master.sys.server_principals P' + CHAR(10) +
        'Left Join '/* + QUOTENAME(@PartnerServer) + '.*/ + 'master.sys.sql_logins L On L.principal_id = P.principal_id' + CHAR(10) +
        'Where P.type In (''U'', ''G'', ''S'')' + CHAR(10) +
        'And P.name <> ''sa''' + CHAR(10) +
        'And P.name Not Like ''##%''' + CHAR(10) +
        'and P.Name Not like ''NT SERVICE%''' + CHAR(10) +
        'And CharIndex(''' + @Machine + '\'', P.name) = 0;';
    
    Insert Into @Logins (Name, SID, IsDisabled, Type, PasswordHash)
    Exec sp_executesql @SQL;
    
    -- Get all roles from principal server
    Set @SQL = 'Select RoleP.name, LoginP.name' + CHAR(10) +
        'From '/* + QUOTENAME(@PartnerServer) + '.*/ + 'master.sys.server_role_members RM' + CHAR(10) +
        'Inner Join '/* + QUOTENAME(@PartnerServer) + .*/ +'master.sys.server_principals RoleP' +
        CHAR(10) + char(9) + 'On RoleP.principal_id = RM.role_principal_id' + CHAR(10) +
        'Inner Join '/* + QUOTENAME(@PartnerServer) + '.*/ + 'master.sys.server_principals LoginP' +
        CHAR(10) + char(9) + 'On LoginP.principal_id = RM.member_principal_id' + CHAR(10) +
        'Where LoginP.type In (''U'', ''G'', ''S'')' + CHAR(10) +
        'And LoginP.name <> ''sa''' + CHAR(10) +
        'And LoginP.name Not Like ''##%''' + CHAR(10) +
        'And LoginP.name Not Like ''NT SERVICE%''' + CHAR(10) +
        'And RoleP.type = ''R''' + CHAR(10) +
        'And CharIndex(''' + @Machine + '\'', LoginP.name) = 0;';
    
    Insert Into @Roles (RoleName, LoginName)
    Exec sp_executesql @SQL;
    
    -- Get all explicitly granted permissions
    Set @SQL = 'Select P.name Collate database_default,' + CHAR(10) +
        '   SP.state_desc, SP.permission_name, SP.class, SP.class_desc, SP.major_id,' + CHAR(10) +
        '   SubP.name Collate database_default,' + CHAR(10) +
        '   SubEP.name Collate database_default' + CHAR(10) +
        'From '/* + QUOTENAME(@PartnerServer) + '.*/ + ' master.sys.server_principals P' + CHAR(10) +
        'Inner Join '/* + QUOTENAME(@PartnerServer) + '.*/ + ' master.sys.server_permissions SP' + CHAR(10) +
        CHAR(9) + 'On SP.grantee_principal_id = P.principal_id' + CHAR(10) +
        'Left Join '/* + QUOTENAME(@PartnerServer) + '.*/ + ' master.sys.server_principals SubP' + CHAR(10) +
        CHAR(9) + 'On SubP.principal_id = SP.major_id And SP.class = 101' + CHAR(10) +
        'Left Join '/* + QUOTENAME(@PartnerServer) + '.*/ + ' master.sys.endpoints SubEP' + CHAR(10) +
        CHAR(9) + 'On SubEP.endpoint_id = SP.major_id And SP.class = 105' + CHAR(10) +
        'Where P.type In (''U'', ''G'', ''S'')' + CHAR(10) +
        'And P.name <> ''sa''' + CHAR(10) +
        'And P.name Not Like ''##%''' + CHAR(10) +
        'And P.name Not Like ''NT SERVICE%''' + CHAR(10) +
        'And CharIndex(''' + @Machine + '\'', P.name) = 0;'
    
    Insert Into @Perms (LoginName, PermState, PermName, Class, ClassDesc, MajorID, SubLoginName, SubEndPointName)
    Exec sp_executesql @SQL;
    
    --select * from @Logins;
    --select * from @Roles;
    --select * from @perms;
    
    
    Select @MaxID = Max(LoginID), @CurrID = 1
    From @Logins;
    
    While @CurrID <= @MaxID
    Begin
    Select @LoginName = Name,
        @IsDisabled = IsDisabled,
        @Type = [Type],
        @SID = [SID],
        @PasswordHash = PasswordHash
    From @Logins
    Where LoginID = @CurrID;
    
    --    If Not Exists (Select 1 From sys.server_principals
    --              Where name = @LoginName)
    Begin
    
        set @sql = char(10);
        set @sql += 'If Not Exists (Select 1 From sys.server_principals Where name = ''' + @LoginName + ''')' + char(10);
        set @sql += 'begin' + char(10) + '    ';
    
        Set @SQL += 'Create Login ' + quotename(@LoginName)
        If @Type In ('U', 'G')
        Begin
            Set @SQL = @SQL + ' From Windows;'
        End
        Else
        Begin
            Set @PasswordHashString = '0x' +
                Cast('' As XML).value('xs:hexBinary(sql:variable("@PasswordHash"))', 'nvarchar(300)');
    
            Set @SQL = @SQL + ' With Password = ' + @PasswordHashString + ' HASHED;  --, ';
    
            Set @SIDString = '0x' +
                Cast('' As XML).value('xs:hexBinary(sql:variable("@SID"))', 'nvarchar(100)');
            Set @SQL = @SQL + 'SID = ' + @SIDString + ';' + char(10);
        End
    
        set @sql += char(10) +
            '    print ''Created Login ' + @loginName  + ''';' + char(10) +
            'end' + char(10) +
            'else' + char(10) +
            convert(nvarchar(max), '    print ''Login ' + @loginName + ' already existed. '';') + char(10);
    
        If @Debug = 0
        insert into #sqlOut select @SQL;                      
        Else
        Print @SQL;
    
        If @IsDisabled = 1
        Begin
            Set @SQL = 'Alter Login ' + quotename(@LoginName) + ' Disable;'
            If @Debug = 0
                insert into #sqlOut select @SQL;                              
            Else              
                Print @SQL;              
        End
        End
    Set @CurrID = @CurrID + 1;
    End
    
    
    insert into #sqlOut select char(10) + 'use Master;' + char(10);
    
    Select @MaxID = Max(RoleID), @CurrID = 1
    From @Roles;
    
    While @CurrID <= @MaxID
    Begin
    Select @LoginName = LoginName,
        @RoleName = RoleName
    From @Roles
    Where RoleID = @CurrID;
    
    /*  If Not Exists (Select 1 From sys.server_role_members RM
                Inner Join sys.server_principals RoleP
                    On RoleP.principal_id = RM.role_principal_id
                Inner Join sys.server_principals LoginP
                    On LoginP.principal_id = RM.member_principal_id
                Where LoginP.type In ('U', 'G', 'S')
                And RoleP.type = 'R'
                And RoleP.name = @RoleName
                And LoginP.name = @LoginName)*/
    Begin
        If @Debug = 0
        Begin          
            insert into #sqlOut select 'Exec sp_addsrvrolemember @rolename = ''' + @RoleName + ''', @loginame = ''' + @LoginName + ''';';
        End
        Else
        Begin
            Print 'Exec sp_addsrvrolemember @rolename = ''' + @RoleName + ''',';
            Print '     @loginame = ''' + @LoginName + ''';';
        End
    End
    
    Set @CurrID = @CurrID + 1;
    End
    
    
    insert into #sqlOut select char(10) + 'use Master;' + char(10);
    
    
    Select @MaxID = Max(PermID), @CurrID = 1
    From @Perms;
    
    While @CurrID <= @MaxID
    Begin
    Select @PermState = PermState,
        @PermName = PermName,
        @Class = Class,
        @LoginName = LoginName,
        @MajorID = MajorID,
        @SQL = PermState + space(1) + PermName + SPACE(1) +
            Case Class When 101 Then 'On Login::' + QUOTENAME(SubLoginName)
                    When 105 Then 'On ' + ClassDesc + '::' + QUOTENAME(SubEndPointName)
                    Else '' End +
            ' To ' + QUOTENAME(LoginName) + ';'
    From @Perms
    Where PermID = @CurrID;
    
    /*If Not Exists (Select 1 From sys.server_principals P
                Inner Join sys.server_permissions SP On SP.grantee_principal_id = P.principal_id
                Where SP.state_desc = @PermState
                And SP.permission_name = @PermName
                And SP.class = @Class
                And P.name = @LoginName
                And SP.major_id = @MajorID)*/
    Begin
        If @Debug = 0
                insert into #sqlOut select @sql;                      
        Else          
            Print @SQL;          
    End
    
    Set @CurrID = @CurrID + 1;
    End
    
    
    select Command from #sqlOut as SqlOut order by Row;
    go
    
    
    --
    -- (6) Generate a script to Re-link all users to logins based on current state (before shutdown)
    --
    
    use Master;
    
    if object_id('tempdb..#sqlOut') is not null
    drop table #sqlOut;
    
    create table #sqlOut
    (
        Command nvarchar(max) not null,
        Row int identity(1,1) not null primary key
    );
    
    insert into #sqlOut select char(10) + '-- RELINK USERS TO LOGINS' + char(10);
    
    insert into #sqlOut select char(10) + char(10) + '/* ---------------------------------------------------------------------------------------------' + char(10) + 
    'ServerName: ' + @@servername + char(10) + 'ServiceName: ' + @@servicename + char(10) + 'Version: ' + @@version + 
    '--------------------------------------------------------------------------------------------- */';
    
    declare @dbCmd varchar(8000) = '
    use ?;
    
    insert into #sqlOut select char(10) + ''use ?;'' + char(10);  
    
    with links as
    (
    select u.name as UserName,
        l.loginname as LoginName
        from sysusers u 
        join master..syslogins l
        on u.sid = l.sid        
    where u.name != ''dbo''
        and u.isSqlUser = 1 or l.isNtName = 1 or l.isNtGroup = 1
    )
    insert into #sqlOut 
    select ''alter user ['' + UserName + ''] with name = ['' + UserName + ''], login = ['' + LoginName + '']''
    from links
    ';    
    
    exec sp_MSforeachdb @dbCmd;
    
    select Command from #sqlOut order by Row;
    
    go

5)スクリプトを実行して、システム(マスター、msdb、モデル)を含むすべてのDBを外部ドライブにバックアップします。

6)スクリプトを実行してすべてのDBを切り離します

7)Cドライブが再フォーマットされます。LDF / MDFがC上にない場合は保存します。

8)Windows Server 2012はCにインストールされます

9)元のシステムファイルのLDF / MDFがCドライブにない場合は邪魔にならない場所に移動します。

10)SQL Server 2012が再インストールされ、SP3にパッチが適用されます。システムユーザー/グループアカウントを再作成する

11)システムDBを新しい場所またはファイル名にバックアップします(元のファイルを上書きしないように注意してください!)。

12)ロールスニペットの再作成を実行します。何かのようなもの:

USE [master]
CREATE SERVER ROLE [SomeServerRole]
--ALTER SERVER ROLE [dbcreator] ADD MEMBER [SomeServerRole]
--ALTER SERVER ROLE [bulkadmin] ADD MEMBER [SomeServerRole]
-- ALTER SERVER ROLE [SomeServerRole] ADD MEMBER [SomeMemberOrRole]

13)ログインスクリプトの再作成を実行します(ログインが復元された場合は何もしません)

14)SQL AGENTを停止します。

(ここでマスターを復元できました、私たちはチキンアウトしました)。

15)上記のスクリプトを使用してmdf / ldfを添付します。a。上記のスクリプトを使用して、手動でbakから復元できない場合。

16)モデルの復元の試行

17)SQLエージェントが停止していることを確認します。MSDBの復元(リンク)a。失敗した場合は、ジョブ+メンテナンスプラン+メール設定+オペレーターを再作成する必要があります

18)ログインするユーザーを開くスクリプト...

    a. If there are master users (rare?) then First Re-Create users for master since it was not restored:
        use master;       
        CREATE USER [ABC] FOR LOGIN [machine\ABC]

    b. Run the rest of the script

19)Service Brokerを有効にして、元の値のSELECT名is_broker_enabled FROM sys.databasesと一致させます。

    alter database MSDB set single_user with rollback immediate;
    ALTER DATABASE [MSDB] SET ENABLE_BROKER;
    alter database MSDB set multi_user;

20)SQLエージェントの開始

21)並列処理のしきい値を元の値に設定

22)データベース設定を元の値に調整します。

 declare @dbCmd varchar(8000) = '
      use ?;
      if db_name() not in (''master'', ''model'', ''tempdb'', ''msdb'')
      begin
             print ''Adjusting [?]...'';    
            alter database [?] set single_user with rollback immediate;
             aLTER AUTHORIZATION ON DATABASE::[?] to [sa];
            -- alter database [?] set trustworthy on;
            ALTER DATABASE [?] SET AUTO_CLOSE OFF WITH NO_WAIT;     
            alter database [?] set multi_user;
      end     
      else
             print ''Skipping [?]...'';
    ';    

    exec sp_MSforeachdb @dbCmd;

23)ジョブの所有権を確認します。

select s.name as JobName, l.name as login, SUSER_SNAME(s.owner_sid) AS login2
from  msdb..sysjobs s 
left join master.sys.syslogins l on s.owner_sid = l.sid

SQL Serverのバージョンもアップグレードされた場合、モデルとmsdbデータベースが復元されたため、https://support.microsoft.com/en-us/kb/264474が原因でジョブが失われたとは思わない

不足しているもの:

  • masterデータベースの元のユーザー(まれですか?)
  • サーバーの役割

0

どちらのアプローチ自体にも問題はありません。私は両方を行いました。両方の結果は通常良好です。

移行アプローチに問題がある場合、それは技術的ではありません。それは怠です。多くの場合、会社がまだxxxxバージョンに完全に移行していない理由は、彼らがSwing移行を選択し、完全に移動するためのハードワークを実行するために回避したことがないためです。現在では、1つではなく2つ以上のサーバーのセットがあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.