it-swarm-eu.dev

Jsou upgrady SQL Server na místě tak špatně doporučeny, jako tomu bývalo?

S SQL serverem pracuji zapínat a vypínat od SQL Server 6.5. Stará rada, která mi stále zvoní v hlavě, nikdy neprováděla místní upgrade.

Aktuálně upgraduji systémy 2008 R2 DEV a TEST na SQL Server 2012 a musím použít stejný hardware. Myšlenka, že nebudu muset obnovit konfiguraci mých Reportingových služeb, je velmi atraktivní a jsem opravdu proti času na zeď. Nejsou zahrnuty žádné analytické služby ani nic neobvyklého nebo nestandardního - jsou nainstalovány pouze databázový stroj a služby hlášení.

Setkal se někdo s vážnými problémy s upgradem na místě? Nebo bych měl přehodnotit svoji pozici ohledně upgradů na místě?

79
DamagedGoods

Opravdu krátká odpověď - Na místě je v pořádku. Poté si můžete zkontrolovat konfiguraci a implementovat osvědčené postupy pro SQL Server 2012.

Delší odpověď na upgrade/migraci serveru SQL

Jedná se tedy o názorovou otázku a neexistuje nutně nesprávná nebo správná odpověď, ale upřednostňuji upgrady migračního stylu na místě z mnoha důvodů. Jak již bylo řečeno - někteří z mých klientů z různých důvodů neměli na výběr, ale provedli na místě a opravdu od SQL Server 2005 nebyly aktualizace na místě tak špatné, jako tomu bývalo.

Proč dávám přednost migraci před upgradem na místě

  • Jednodušší vrácení - Pokud se něco pokazí, můžete se vrátit zpět jednoduchým slovy „Přerušili jsme aktualizaci. Změňte připojovací řetězce na starý server, dokud to vyřešíme“ . Díky místu to opravujete nebo jste dole.
  • Obnovit hardware - Hardware se rychle mění. Můžete snadno uvíznout na hardwaru, který byl vhodný pro vaši společnost před 4 lety, ale není vhodný pro dnešek a další čtyři roky díky in-place upgrade. Pravděpodobně budete muset někdy provést migraci nového hardwaru.
  • Cítit se lépe - Jistě ... Toto je subjektivní, ale je dobré vědět, že začínáte s novou instalací OS, novou instalací SQL bez pavučiny od osoby v zaměstnání před vámi (nebo dříve, než jste věděli, co jste dnes věděli), což by vám v budoucnu mohlo způsobit bolesti hlavy.
  • Nový operační systém - Migrace vám dává šanci začít s novou verzí operačního systému, pokud nejste dnes poslední a největší.
  • Můžete to vyzkoušet - Chtěli byste někdy získat sadu základních linií na novém stroji před instalací SQL a zamlžit jej pomocí databází a využití? Můžete to udělat hned.
  • Někdy je snazší propašovat v osvědčených postupech - Možná byl účet služby SQL Server místním správcem. Možná, že Builtin Administrators je v roli serveru SA). Možná, že věci byly nějak hackovány dohromady, aby to fungovalo dříve. Můžete to vše opravit a začít znovu.
  • Testovací prostředí zdarma a extra spánek - Je velkým přínosem mít prostředí, ve kterém můžete pracovat před skutečným dnem ukončení, když vytvoříte toto nové prostředí žít. Pokud provedete migraci do nového prostředí, můžete si ji postavit během pracovní doby, a to ještě před skutečným dnem omezení a vyzkoušet ji v mnoha ohledech dopředu. Můžete provádět úplné regresní testování ve všech aplikacích a systémech celé dny a mít velký klid, než skutečně provedete konečnou sadu obnovení/připojování a omezování všech aplikací a přístupu do nového prostředí.
  • Nemusíte to dělat všechno najednou - Velmi běžná situace, do které narazím, je prostředí, které se snaží konsolidovat na několik málo případů . Možná jeden na verzi, možná jeden na "úroveň" a verzi. Mnoho z těchto projektů má různé časové osy pro různé aplikace a databáze založené na testování, projektových plánech a včasnosti certifikace dodavatelů. Provádění migrace znamená, že můžete přesunout ty databáze, které jsou připraveny, když jsou připraveny, a stále zpracovávat žádosti o databáze, které se nemohou pohybovat z jednoho nebo druhého důvodu.

Všímám si Neříkám, že musíš udělat to jako migraci . In-Place funguje a funguje dobře, pokud neplánujete nákup nového hardwaru ve vašem rozpočtu a nemůžete to udělat pro tuto aktualizaci. Podpora v procesu upgradu je mnohem lepší, než tomu bylo v 6,5 dne, takže se tím nedostanete do špatné pozice.

Pokud plánujete provádět dev/test na místě, ale chcete provést migraci pro produkci, měli byste zvážit provedení alespoň jedné migrace před produkcí. Tímto způsobem si můžete předem naplánovat kontrolní seznam a vypořádat se s případnými problémy, na které jste nemysleli.

Připojit/Odpojit vs. Zálohování/Obnovení pro migrace

Pokud se rozhodnete přistoupit k migračnímu přístupu, existuje ještě jedno rozhodnutí, o kterém možná budete mít debatu, a tak přesunete databázi do nového prostředí. Můžete buď odpojit databázi od starého serveru a připojit ji k novému, nebo ji zálohovat a obnovit tam.

Dávám přednost zálohování/obnově. Největší výhodou, kterou slyším o odpojení/připojení, je to, že šetří čas. Pro mě záloha/obnovení vyhrává z několika důvodů:

  • Zachovat staré dostupné - To vám umožní mít stále přístupnou databázi na zdrojovém serveru. odpojit/připojit by mělo udělat totéž, ale bude vyžadovat několik kroků a existuje prostor pro lidské chyby s odpojením/připojením, které by to mohly komplikovat.
  • Zaručujete, že máte zálohu - Místo toho, abyste pouze odebrali databázi z detachu a případně zapomněli krok zálohování, zajistili jste, že Vzal jsem si tu zálohu.
  • Lidská chyba - Pokud odstraníte nesprávný soubor, zapomeňte na to, kam něco posíláte nebo jinak pokazíte vaše kroky, riskujete tím, že přesouváte data a logujete soubory kolem vaší databáze. Nyní to můžete zmírnit zkopírováním namísto řezání (a pokud se odpojíte, měli byste se dostat ze zvyku vyjmout a vložit), ale mohli byste se zbavit nepořádku. SQL Server již tyto soubory nezamyká a je prostě příliš snadné smazat soubor náhodně, abych ho riskoval.
  • Není to opravdu , že pomalejší - pořizování zálohy a kopírování je o něco více času, ale není to tak moc, že ​​bych za to ochoten zaplatit další riziko. Ve skutečnosti - při použití úplného modelu obnovy a zálohování protokolu můžete snížit výpadky ještě více při cutovers, jak je popsáno níže v části „Jak rychlejší přístup k migraci“

Pokud se rozhodnete provést zálohu/obnovu - to znamená, že vaše stará zdrojová databáze bude stále online. Po provedení zálohy ráda uvedu tuto databázi do režimu offline. Někdy jdu ještě o krok dále a celou instanci SQL provádím offline poté, co jsem odepsal zabezpečení, úlohy, propojený server, certifikáty, nastavení databázové pošty a další informace o celé instanci. Tím se zabrání problému během testování, kdy někdo řekne „Všechno vypadá skvěle!“ jen den nebo dva si uvědomit, že mluvili se starou databází na starém serveru. Přepnutí těchto databází do režimu offline nebo celé instance offline vám umožní zabránit těmto falešným pozitivům a nepořádkům, které vytvoří.

Jak rychlejší přístup k migraci

Využitím úplného modelu obnovy můžete minimalizovat prostoje potřebné pro přechod ze starého na nové prostředí pro rušné produkční prostředí s malým prostojem. Zjednodušeně řečeno - prostředí, do kterého migrujete, obnovte nejnovější úplnou zálohu, všechny rozdílové zálohy a všechny již přijaté zálohy protokolu určující NORECOVERY - pak vše, co budete muset udělat pro konečné snížení, je obnovení záloh protokolu které ještě nebyly obnoveny, a poslední zálohu protokolu, kterou chcete obnovit, zadáním WITH RECOVERY. Tímto způsobem lze pro rozsáhlou databázi skutečné okno výpadku drasticky minimalizovat tím, že se zaplatí náklady na plný, diferenční a většina protokolů se obnoví před časem výpadku. Díky Tao za to, že jste na to poukázali v komentářích!

Jak zajistit bezpečnější upgrade na místě

Při volbě místního přístupu můžete udělat několik věcí, abyste zlepšili své zkušenosti a výsledky.

  • Záloha - Vezměte si vhodné zálohy všech uživatelských a systémových databází vašeho prostředí předem a ujistěte se, že jsou dobré (jsem paranoidní. Vlastně bych obnovte je někde, aby opravdu věděli, že jsou dobří. Může to ztrácet čas .. Ale v případě katastrofy se můžete poděkovat.) Skriptujte veškeré konfigurační informace o instalaci SQL a OS v tomto prostředí.
  • Vyzkoušejte věci dobře před zahájením - Ověřte, zda máte dobré prostředí a dobré databáze. Měli byste dělat věci, jako je prohlížení protokolů chyb a pravidelné spouštění DBCC CHECKDB, ale před provedením místní aktualizace je skvělý čas začít. Opravte problémy předem.
  • Zajistěte zdravotní stav operačního systému - Nezkoušejte pouze, zda je SQL zdravý, ujistěte se, že je váš server zdravý. Máte nějaké hrubé chyby v protokolech událostí systémů nebo aplikací? Jaký je váš volný prostor?
  • Připravte se na nejhorší - Před nějakou dobou jsem měl sérii příspěvků na blogu, která šla za předpokladu, že pokud se připravujete na selhání - ve skutečnosti se připravujete na selhání .. Stále tomu věřím. Takže přemýšlejte o problémech, které můžete mít, a vypořádejte se s nimi podle toho v předstihu. Dostaňte se do myšlení „selhání“ a budete myslet na věci, které byste jinak neměli.

Význam kontrolních seznamů pro upgrade nebo migraci

Pokud se rozhodnete provést upgrade (na místě nebo migraci), měli byste vážně zvážit vytvoření kontrolního seznamu a použití tohoto kontrolního seznamu v každém prostředí. Do tohoto kontrolního seznamu byste měli zahrnout spoustu věcí, v neposlední řadě:

  1. Na začátku - Provádějte některé kroky, jako je provedení testovací aktualizace, testování aplikací na nejnovější úrovni kompatibility databáze a zvážení spuštění nástroje, jako je SQL Server Upgrade Advisor předem, abyste zjistili, jaké úkoly je třeba provést před provedením upgradu nebo migrace serveru SQL.
  2. Předběžné kroky - Vyčištění, úlohy operačního systému, oprava předem, příprava aplikací pro upgrade (čisté vypnutí, práce s řetězci připojení), zálohy atd.
  3. Kroky pro upgrade/migraci - Vše, co musíte udělat, aby aktualizace nebo migrace byla úspěšná a ve správném pořadí. Instalace, změna (nebo neměnící se v závislosti na vašem testování a přístupu) změny režimu kompatibility v databázích atd.
  4. Kroky po migraci/upgradu - Různé testy, zveřejnění nové verze nebo nové možnosti konfigurace serveru, implementace osvědčených postupů, změny zabezpečení atd.
  5. Kroky pro vrácení - Po celou dobu byste měli mít kroky a milníky pro vrácení. Pokud se dostanete tak daleko a stane se to, co uděláte? Jaká jsou kritéria „udělat úplné vrácení“? A jak to uděláte (zpětné změny řetězce připojení, změna nastavení zpět, návrat k původní verzi, přeinstalace, pokud je na místě, přejděte zpět na starý server, pokud migrace atd.)

A pak nechte osobu, která bude provádět upgrade výroby, sledovat kontrolní seznam v jiném prostředí, než je výroba - zejména ta, která uzavírá podobnou produkci, pokud je to možné („jižně od prod“, jak říkám ...), a poznamenejte si jakékoli problémy nebo body kde se museli odklonit od kontrolního seznamu nebo improvizovat kvůli nedostatku kontrolního seznamu. Poté se změny sloučí a se pobaví se změnou vaší výroby.

Nemohu zdůraznit důležitost testování důkladně po migraci nebo upgradu a před migrací dostatečně. Rozhodování o vrácení prostředků během upgradu by mělo být snadné - zejména během migrace. Pokud je něco nepříjemného, ​​vraťte se zpět a zjistěte, jestli to nedokážete účinně a spolehlivě vyřešit v horku migrace. Jakmile žijete v tomto novém prostředí a uživatelé se připojují - vrácení zpět se stává obtížným úkolem. Nelze obnovit databázi serveru SQL na předchozí verzi. To znamená manuální práci a migraci dat. Vždy počkám několik týdnů, než zabiju staré prostředí, ale měli byste udělat vše, co je v našich silách, abyste se vyhnuli potřebě tohoto starého prostředí tím, že zjistíte všechny své problémy, než se vaši živí uživatelé někdy dotknou nového prostředí. Předtím, než začnete s upgradem/migrací.

Rychlá poznámka o migraci/upgradu služby SQL Server Reporting Services Migrace instalace SSRS není docela herkulovským úkolem, o kterém si mnozí myslí, že je. Tento technet/books online článek je vlastně docela užitečný . Jedním z nejdůležitějších výroků v tomto článku je „Zálohujte šifrovací klíče“ , zejména pokud máte spoustu uložených citlivých informací, jako je naplánované hlášení e- e-mailové adresy příjemců e-mailu, informace o připojení pro více připojení atd. Můžete požádat jednoho z mých klientů od chvíle, jak je to důležité. Vědí to, protože jsem si tenhle nepořádek zaslechl a strávil dost času úpravou plánů sestav a oprávnění pro připojovací řetězce.

92
Mike Walsh

Podle mých zkušeností by měl být stejný rozhodovací proces proveden jako předchozí. AFAIK nedošlo k žádné „světové změně“ s instalací SQL Serveru, v rámci samotného produktu MS SQL Server a potenciálních problémů, které máte při zavádění softwaru s miliony řádků kódu. Mohlo by se stát něco špatného a nyní jste uvízl bez možnosti „ROLLBACK“.

Máte však jiné alternativy. Můžete zvážit vytvoření snímku systému, obnovit jinde, provést upgrade a zjistit, co se stane. Tento test by vám měl poskytnout spoustu pohodlí, ale není to zcela zaručeno, že na prod boxu nevzniknou žádné problémy. Toto je však možnost, která nebyla k dispozici zpět za 6,5 ​​dne SQL.

Jen bych předpokládal nejhorší scénář. Provádíte upgrade na místě a nešťastně selže. Musíte se z toho zotavit ve svém RTO a RCO. Rozumí podnikání rizikům a máte plány na jejich zmírnění?

Pokud by to s tím nebylo v pořádku, pak to nedělejte, byla by to moje rada.

14
Ali Razeghi

Pokud máte servery spuštěné ve virtuálním prostředí, můžete provést snímek na klonu a poté použít místní upgrade a otestovat instanci, aby byla oprava úspěšná. Pokud to funguje, můžete použít snímek a provést klonování produkčního serveru. Pokud to nefunguje špatně, můžete snímek odstranit a vrátit se k obrazu před upgradem a zkusit to znovu, nebo odstranit klon a úplnou migraci.

2
Troy

Kvůli velké investici do hardwaru jsme byli povinni upgradovat pouze operační systém při zachování aktuální verze serveru SQL (2012, 3 servery, 22 instancí, ~ 300 databází). Žádná složitá nastavení, jako je zrcadlení atd.

Tento příklad neodpovídá otázce přesně, protože SQL Server není upgradován. Myslím, že je to stále dobrá odpověď, protože uvedené kroky by ve skutečnosti byly jednodušší než skutečná migrace na místě.

Přehled: Externí jednotka byla připojena k plnému zálohování hlavně jako preventivní opatření. Z externího disku se skutečně obnoví pouze model a msdb. Ldf/mdf byly ponechány na místě pro odpojení/připojení. Na některé místní účty se odkazovalo v rámci databází. Poté, co byly znovu vytvořeny v OS, byly znovu vytvořeny odkazy v DB (protože se mohou změnit SID).

Pak zde byly kroky, které pro nás fungovaly:

1) Vezměte na vědomí nastavení na úrovni serveru, které bude obnoveno v krocích 12 (serverové role) a 18 až 23.

2) Oprava SQL Server 2012 na SP3 (vyžaduje konzistenci, pokud chceme obnovit všechny systémové dbs).

3) Ověřte, zda verze odpovídají každé instanci. "Vyberte @@ verzi"

4) Generováním těchto 6 skriptů spusťte tento skript. Redgate SQL Multiscript je obrovským časovým šetřičem, pokud existuje mnoho instancí (Upravte Nástroje -> Možnosti => Délka řádku na maximum (8192) a poté použijte textový výstup).

  • Záloha
  • Obnovit
  • Odpojit
  • Připojit
  • Znovu vytvořte přihlášení
  • Připojte uživatele k přihlášení

    -- (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 @[email protected]_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 '--'[email protected] 
    
    OPEN DBFiles_cursor
    FETCH NEXT FROM DBFiles_cursor INTO @filename
    
    WHILE @@FETCH_STATUS = 0
    BEGIN   
    set @[email protected]_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 @[email protected]_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) Spusťte skript pro zálohování všech databází včetně systému (master, msdb, model) na externí jednotku.

6) Spusťte skript pro odpojení všech databází

7) Jednotka C bude přeformátována. Zachovejte LDF/MDF, pokud nebyly na C.

8) Windows Server 2012 je nainstalován na C

9) Přesuňte LDF/MDF pro původní systémové soubory z cesty, pokud nebyly na jednotce C.

10) SQL Server 2012 bude znovu nainstalován a opraven do SP3 a. Znovu vytvořte systémové uživatelské/skupinové účty

11) Zálohujte systémové DB do NOVÉHO umístění nebo názvu souboru (pozor, abyste nepřepsali originály!).

12) Spusťte úryvek znovu vytvořených rolí. Něco jako:

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) Spusťte znovu přihlašovací skript (nedělá nic, pokud byly obnoveny přihlašovací údaje)

14) Zastavte SQL AGENT.

(Mohl bych zde obnovit Mistra, vystrčili jsme se).

15) Připojte mdf/ldf pomocí skriptu shora. A. Pokud selže ručně obnovit z bak pomocí skriptu z výše.

16) Pokus o obnovení modelu

17) Zajistěte zastavení agenta SQL. Obnovte MSDB (link) a. Pokud selže, je třeba znovu vytvořit úlohy + plán údržby + konfiguraci pošty + operátory

18) Otevřít skript pro přihlášení uživatele ...

    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) Povolit zprostředkovateli služeb, aby odpovídal původní hodnotě SELECT name, 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) Spusťte agenta SQL

21) Nastavte práh rovnoběžnosti na původní hodnotu

22) Upravte všechna nastavení databáze na jejich původní hodnoty:

 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) Zkontrolujte vlastnictví úlohy:

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

Pokud by byla také upgradována verze serveru SQL, nemyslím si, že by mohly být obnoveny databáze a databáze msdb, takže by úlohy byly ztraceny kvůli https://support.Microsoft.com/en-us/kb/264474

Co chybí:

  • Orignální uživatelé v hlavní databázi (vzácné?)
  • Role serveru
  • ?
1
crokusek

S přístupem samo o sobě není nic špatného - udělal jsem obojí a oba výsledky jsou obvykle dobré.

Pokud existuje problém s migračním přístupem, není to technické: je to lenost. Příliš často zjišťuji, že důvodem, proč společnost dosud nešla plně do xxxx verze, je to, že si vybrali migrační otáčení a nikdy se neobešli, aby tvrdě pracovali, aby se úplně pohnuli. Nyní mají místo jednoho jednoho nebo více serverů.

0
RowlandG