AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 29328
Accepted
DamagedGoods
DamagedGoods
Asked: 2012-11-27 17:10:45 +0800 CST2012-11-27 17:10:45 +0800 CST 2012-11-27 17:10:45 +0800 CST

As atualizações in-loco do SQL Server são tão desaconselhadas quanto costumavam ser?

  • 772

Eu tenho trabalhado com o SQL Server dentro e fora desde o SQL Server 6.5, o velho conselho que ainda soa na minha cabeça era nunca fazer uma atualização in-loco.

Atualmente estou atualizando meus sistemas 2008 R2 DEV e TEST para SQL Server 2012 e preciso usar o mesmo hardware. A ideia de não ter que restaurar a configuração do meu Reporting Services é muito atraente e estou realmente contra a parede em termos de tempo. Não há serviços de análise envolvidos ou qualquer coisa incomum ou fora do padrão - apenas o mecanismo de banco de dados e os serviços de relatórios são instalados.

Alguém já teve problemas sérios com atualizações in-loco? Ou devo reavaliar minha posição sobre atualizações no local?

sql-server sql-server-2012
  • 5 5 respostas
  • 27846 Views

5 respostas

  • Voted
  1. Best Answer
    Mike Walsh
    2012-11-27T17:19:43+08:002012-11-27T17:19:43+08:00

    Resposta realmente curta - No lugar está tudo bem. Você pode revisar sua configuração posteriormente e implementar as práticas recomendadas para o SQL Server 2012.

    Uma resposta mais longa sobre atualizações/migrações do SQL Server

    Portanto, isso é uma questão de opinião e não há uma resposta necessariamente errada ou certa, mas prefiro atualizações de estilo de migração no local por vários motivos. Dito isto - alguns dos meus clientes, por várias razões, não tiveram escolha a não ser fazer um in-loco e, desde o SQL Server 2005, as atualizações in-loco não são tão ruins quanto costumavam ser.

    Por que prefiro uma migração para uma atualização in-loco

    • Reversão mais fácil - Se algo der errado, você pode reverter simplesmente dizendo "nós abortamos a atualização. Por favor, altere as strings de conexão para o servidor antigo enquanto resolvemos isso". Com um in-place você está consertando ou você está para baixo.
    • Atualizar Hardware - O hardware muda rapidamente. Você pode facilmente ficar preso em um hardware que era certo para sua empresa há 4 anos, mas não adequado para hoje e nos próximos quatro anos com uma atualização no local. Você provavelmente terá que fazer uma migração em algum momento para o novo hardware.
    • Feel Better - Claro... Este é subjetivo, mas é bom saber que você está começando com uma nova instalação do SO, uma nova instalação do SQL sem teias de aranha da pessoa no trabalho antes de você (ou você antes de saber o que sabia hoje) que poderia causar dores de cabeça no futuro.
    • Novo sistema operacional - Uma migração oferece a chance de começar com uma nova versão do sistema operacional se você não estiver usando a melhor e mais recente hoje.
    • Você pode testá-lo - Sempre desejou obter um conjunto de linhas de base em uma nova máquina antes de instalar o SQL e adicioná-lo à nuvem com bancos de dados e uso? Você pode fazer isso agora.
    • Às vezes, é mais fácil se infiltrar nas práticas recomendadas - talvez a conta de serviço do SQL Server fosse um administrador local. Talvez os Administradores internos estejam na função de servidor SA. Talvez as coisas tenham sido meio que hackeadas para fazer funcionar antes. Você pode consertar tudo isso e começar de novo.
    • Ambiente de teste gratuito e sono extra - É um grande benefício ter um ambiente no qual você possa trabalhar antes do dia de transição real quando você ativar esse novo ambiente. Fazer uma migração para um novo ambiente significa que você pode criá-lo durante o horário comercial, bem antes do seu dia real de transição e testá-lo de várias maneiras antes do tempo. Você pode executar testes de regressão completos em todos os aplicativos e sistemas por dias e ficar tranquilo antes de realmente fazer o conjunto final de restaurações/anexações e transferência de todos os aplicativos e acesso ao novo ambiente.
    • Você não precisa fazer tudo de uma vez - Uma situação muito comum que encontro é um ambiente que está tentando se consolidar em apenas algumas instâncias. Talvez um por versão, talvez um por "camada" e versão. Muitos desses projetos têm cronogramas diferentes para vários aplicativos e bancos de dados com base em testes, planos de projeto e pontualidade de certificação de fornecedores. Fazer a migração significa que você pode mover os bancos de dados que estão prontos, quando estiverem prontos, e ainda lidar com solicitações para os bancos de dados que não podem ser movidos por um motivo ou outro.

    Lembre-se que não estou dizendo que você tem que fazer isso como uma migração. O In-Place funciona e funciona bem se você não estiver planejando comprar um novo hardware em seu orçamento e não puder fazer isso para esta atualização. O suporte no processo de atualização é muito melhor do que nos 6,5 dias, então você não está se colocando em uma posição ruim fazendo isso.

    Se você planeja fazer in-loco para desenvolvimento/teste, mas deseja fazer uma migração para produção, considere fazer pelo menos uma migração antes da produção. Dessa forma, você pode elaborar sua lista de verificação com antecedência e lidar com possíveis problemas nos quais não estava pensando.

    Anexar/Desanexar vs. Backup/Restauração para Migrações

    Se você decidir seguir a abordagem de migração, ainda há mais uma decisão sobre a qual você ainda pode debater e é como você move seu banco de dados para o novo ambiente. Você pode desanexar seu banco de dados do servidor antigo e anexá-lo ao novo ou fazer backup e restaurá-lo lá.

    Eu prefiro backup/restauração. A maior vantagem que ouvi sobre detach/attach é que economiza algum tempo. Para mim, backup/restauração ganha por alguns motivos:

    • Manter o antigo acessível - Isso permite que você ainda tenha um banco de dados acessível no servidor de origem. detach/attach deve fazer o mesmo, mas exigirá algumas etapas e há espaço para erro humano com detach/attach que pode complicar isso.
    • Você está garantindo que tem um backup - Em vez de apenas pegar um banco de dados de uma desanexação e potencialmente esquecer uma etapa de backup, você se certificou de ter feito esse backup.
    • Erro humano - Se você excluir o arquivo errado, esquecer para onde está enviando algo ou atrapalhar suas etapas, você arrisca muito movendo os dados e os arquivos de log para seu banco de dados. Agora você pode mitigar isso copiando em vez de cortar (e se você desanexar, você deve sair do hábito de cortar e colar), mas você ainda pode estragar tudo. O SQL Server não está mais bloqueando esses arquivos e é muito fácil excluir um arquivo acidentalmente para que eu o arrisque.
    • Não é realmente tão lento - Fazer um backup e copiá-lo é um pouco mais de tempo, mas não é tanto que eu esteja disposto a pagar o risco extra por isso. Na verdade - usando o modelo de recuperação completa e backups de log, você pode reduzir ainda mais o tempo de inatividade para cutovers, conforme descrito abaixo em "Como tornar a abordagem de migração mais rápida"

    Se você decidir fazer o backup/restauração - isso significa que seu banco de dados de origem antigo ainda estará online. Eu gosto de deixar esse banco de dados offline depois de fazer o backup. Às vezes, dou um passo adiante e coloco toda a instância do SQL offline depois de criar scripts de segurança, trabalhos, servidor vinculado, certificados, configurações de correio de banco de dados e outras informações de toda a instância. Isso evita um problema durante o teste em que alguém diz "Tudo parece ótimo!" apenas para perceber um ou dois dias depois que eles estavam conversando com o banco de dados antigo no servidor antigo. Colocar esses bancos de dados offline ou toda a instância offline permite que você evite esses falsos positivos e a bagunça que eles fazem.

    Como tornar a abordagem de migração mais rápida

    Você pode minimizar o tempo de inatividade necessário para a transição de um ambiente antigo para um novo para um ambiente de produção ocupado com pouco tempo de inatividade utilizando o modelo de recuperação completo. Basicamente - prepare o ambiente para o qual você está migrando restaurando o backup completo mais recente, quaisquer backups diferenciais e quaisquer backups de log já feitos especificando NORECOVERY- então tudo o que você terá que fazer para o corte final é restaurar os backups de log que ainda não foram restaurados e o backup de log final que você deseja restaurar especificando WITH RECOVERY. Dessa forma, para um banco de dados grande, a janela de tempo de inatividade de cutover real pode ser drasticamente minimizada pagando o custo das restaurações completas, diferenciais e da maioria dos logs antes da janela de tempo de inatividade. Obrigado ao Tao por apontar isso nos comentários!

    Como tornar a atualização in-loco mais segura

    Algumas coisas que você pode fazer para melhorar sua experiência e resultados ao escolher a abordagem no local.

    • Backup - Faça backups apropriados de todos os bancos de dados de usuários e sistemas do seu ambiente com antecedência e certifique-se de que eles estejam bons (eu sou paranóico. Mas você pode agradecer a si mesmo no caso de um desastre).
    • Teste bem antes de começar - Verifique se você tem um bom ambiente e bons bancos de dados. Você deve fazer coisas como examinar os logs de erros e executar o DBCC CHECKDB regularmente, mas antes de fazer uma atualização in-loco é um ótimo momento para começar. Corrija quaisquer problemas com antecedência.
    • Garanta a integridade do sistema operacional - não apenas certifique-se de que o SQL esteja íntegro, certifique-se de que seu servidor esteja íntegro. Algum erro grave nos logs de eventos de erro do sistema ou do aplicativo? Como está o seu espaço livre?
    • Prepare-se para o pior - eu tinha uma série de posts no blog há algum tempo que partia da premissa de que se você não está se preparando para o fracasso - você está realmente se preparando para falhar .. Eu ainda acredito nisso. Portanto, pense nos problemas que você pode ter e lide com eles de acordo com antecedência. Entre na mentalidade de "fracasso" e você pensará em coisas que não teria de outra forma.

    A importância das listas de verificação de atualização ou migração

    Se você decidir fazer uma atualização (seja no local ou migração), considere seriamente criar uma lista de verificação e usá-la em cada ambiente. Você deve incluir um monte de coisas nesta lista de verificação, entre as quais:

    1. No início - Faça algumas coisas como realizar uma atualização de teste, testar seus aplicativos no nível de compatibilidade de banco de dados mais recente e considerar a execução de uma ferramenta como o SQL Server Upgrade Advisor com antecedência para ver que tipo de tarefas você precisa concluir antes de fazer o SQL Atualização ou migração do servidor.
    2. Pré-etapas - Limpeza, tarefas do sistema operacional, correção antecipada, preparação de aplicativos para a atualização (desligamentos limpos, trabalho de cadeia de conexão), backups , etc.
    3. Etapas de atualização/migração - Tudo o que você precisa fazer para que a atualização ou migração seja bem-sucedida e na ordem certa. Instalação, alteração (ou não alteração, dependendo do seu teste e abordagem) alterações no modo de compatibilidade para bancos de dados, etc.
    4. Etapas de pós-migração/atualização - Vários testes, pós-nova versão ou novas opções de configuração do servidor, implementação de melhores práticas, alterações de segurança, etc.
    5. Etapas de reversão - Ao longo do caminho, você deve ter etapas e marcos de reversão. Se você chegar tão longe e isso acontecer, o que você vai fazer? Quais são os critérios "fazer uma reversão completa"? E como você faz essa reversão (alterações de string de conexão reversas, alterar configurações de volta, voltar para a versão antiga, reinstalar se estiver no local, apontar de volta para o servidor antigo se houver migração etc.)

    E então faça com que a pessoa que fará a atualização de produção siga a lista de verificação em algum ambiente diferente da produção - especialmente um que se pareça com a produção, se possível ("Sul da produção", como eu digo ...) e anote quaisquer problemas ou pontos onde eles tiveram que desviar da lista de verificação ou improvisar devido a uma falta na lista de verificação. Em seguida, junte as alterações e divirta -se com sua alteração de produção.

    Eu não posso enfatizar a importância de testar completamente após a migração ou atualização e antes de sua migração o suficiente. Tomar uma decisão de reversão no meio de uma atualização deve ser fácil - especialmente durante uma migração. Se houver algo desconfortável, reverta e descubra se você não puder solucioná-lo de maneira eficaz e confiável no calor da migração. Quando você estiver ao vivo nesse novo ambiente e os usuários se conectarem, a reversão se tornará uma tarefa difícil. Você não pode restaurar um banco de dados SQL Server para uma versão anterior. Isso significa trabalho manual e migrações de dados. Eu sempre espero algumas semanas para matar o ambiente antigo, mas você deve fazer todo o possível para evitar a necessidade desse ambiente antigo, encontrando todos os seus problemas antes que seus usuários ativos toquem no novo ambiente. De preferência antes mesmo de iniciar a atualização/migração.

    Nota rápida sobre migração/atualização do SQL Server Reporting Services Migrar uma instalação do SSRS não é uma tarefa hercúlea que muitos pensam que é. Este artigo online de technet/books é realmente bastante útil . Uma das advertências mais importantes nesse artigo é "Faça backup das chaves de criptografia" , especialmente se você tiver muitas informações confidenciais salvas, como endereços de e-mail de destinatários de e-mail de relatório agendado, informações de conexão para várias conexões, etc. posso perguntar a um dos meus clientes de algum tempo atrás o quão importante isso é. Eles sabem porque eu estraguei essa etapa e gastei muito tempo modificando agendas de relatórios e permissões de string de conexão.

    • 95
  2. Ali Razeghi - AWS
    2012-11-27T17:17:07+08:002012-11-27T17:17:07+08:00

    Na minha experiência, o mesmo processo de tomada de decisão deve ser feito anteriormente. AFAIK não houve 'mudanças de mundo' com a instalação do SQL Server, dentro do produto MS SQL Server em si, e os problemas potenciais que você tem ao lançar software com milhões de linhas de código. Algo ruim pode acontecer e agora você está preso sem a opção 'ROLLBACK'.

    No entanto, você tem outras alternativas no lugar. Você pode considerar fazer um instantâneo do sistema, restaurar em outro lugar, realizar a atualização e ver o que acontece. Este teste deve lhe dar muito conforto, mas não garante absolutamente nenhum problema na caixa do produto. No entanto, essa é uma opção que não estava disponível nos dias do SQL 6.5.

    Eu apenas assumiria o pior cenário. Você faz uma atualização no local e falha miseravelmente. Você precisa se recuperar disso dentro do seu RTO e RCO. A empresa entende os riscos e você tem planos para mitigá-los?

    Se o negócio não está bem com isso, então não faça isso seria meu conselho.

    • 15
  3. Troy
    2013-12-30T08:29:15+08:002013-12-30T08:29:15+08:00

    Se você tiver seus servidores em execução em um ambiente virtual, poderá executar um instantâneo em um clone e, em seguida, aplicar a atualização in-loco e testar a instância para verificar se a atualização foi bem-sucedida. Se funcionar, você pode aplicar o instantâneo e tornar o clone o servidor de produção. Se tudo der errado, você pode excluir o instantâneo e voltar para a imagem de pré-atualização para tentar novamente ou excluir o clone e fazer uma migração completa.

    • 4
  4. crokusek
    2015-12-18T20:25:49+08:002015-12-18T20:25:49+08:00

    Devido a um grande investimento em hardware, fomos obrigados a atualizar apenas o SO, mantendo a versão atual do SQL Server (2012, 3 servidores, 22 instâncias, ~300 bancos de dados). Sem configurações complexas como espelhamento, etc.

    Este exemplo não corresponde exatamente à pergunta, pois o SQL Server não está sendo atualizado. Eu acho que essa ainda é uma boa resposta porque as etapas mostradas seriam realmente mais simples do que uma migração verdadeira no local.

    Visão geral: Uma unidade externa foi anexada para fazer backups completos principalmente como precaução. Apenas o modelo e o msdb serão realmente restaurados da unidade externa. O ldf/mdf foi deixado no lugar para desanexar/anexar. Algumas contas locais foram referenciadas nos BDs. Depois que eles foram recriados no SO, as referências dentro do banco de dados foram recriadas (já que os SIDs podem mudar).

    Então, aqui estão as etapas que funcionaram para nós:

    1) Anote as configurações de nível de servidor que serão restauradas nas etapas 12 (Funções de servidor) e 18 a 23.

    2) Patch SQL Server 2012 para SP3 (consistência necessária se quisermos restaurar qualquer banco de dados do sistema).

    3) Verifique se as versões correspondem em cada instância. "Selecione @@versão"

    4) Gere esses 6 scripts executando este script. Redgate SQL Multiscript é uma economia de tempo enorme se houver muitas instâncias (Ajuste as Ferramentas -> Opções => Comprimento da Linha ao máximo (8192) e use a Saída de Texto).

    • Cópia de segurança
    • Restaurar
    • Separar
    • Anexar
    • Recriar logins
    • Revincular usuários a logins

      -- (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) Execute o script para fazer backup de todos os bancos de dados, incluindo o sistema (master, msdb, modelo) para a unidade externa.

    6) Execute o script para desanexar todos os bancos de dados

    7) O Drive C será reformatado. Preserve os LDF/MDFs se eles NÃO estiverem em C.

    8) O Windows Server 2012 está instalado em C

    9) Mova o LDF/MDF para arquivos originais do sistema para fora do caminho se eles não estiverem na unidade C.

    10) O SQL Server 2012 será reinstalado e corrigido para o SP3 a. Recriar contas de usuário/grupo do sistema

    11) Faça backup dos BDs do sistema para um NOVO local ou nome de arquivo (cuidado para não substituir os originais!).

    12) Run recreate roles snippet. Something like:

    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) Run recreate login script (doesn't do anything if logins were restored)

    14) Stop SQL AGENT.

    (Could restore Master here, we chickened out).

    15) Attach mdf/ldf using script from above. a. If fail manually restore from bak using script from above.

    16) Attempt Restore of Model

    17) Ensure SQL Agent is stopped. Restore MSDB (link) a. If fails, need to re-create jobs + maintenance plan + mail configuration + operators

    18) Open User To Login script...

        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) Enable service broker to match original value 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) Start SQL Agent

    21) Set Parallelism threshold to original value

    22) Adjust any database settings to their original values:

     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) Check job ownership:

    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
    

    If the SQL Server Version had also been upgraded I don't believe the model and msdb databases could have been restored so jobs would have been lost due to https://support.microsoft.com/en-us/kb/264474

    What's missing:

    • Orignal users in master database (rare?)
    • Server Roles
    • ?
    • 2
  5. RowlandG
    2014-06-03T12:26:49+08:002014-06-03T12:26:49+08:00

    Nada está errado com nenhuma das abordagens em si - eu fiz as duas e ambos os resultados são tipicamente bons.

    Se houver um problema com a abordagem de migração, não é técnico: é preguiça. Muitas vezes, acho que a razão pela qual uma empresa ainda não foi totalmente para a versão xxxx é porque eles escolheram uma migração swing e nunca conseguiram fazer o trabalho duro para se mudar completamente. Agora eles têm dois ou mais conjuntos de servidores em vez de um.

    • 1

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como ver a lista de bancos de dados no Oracle?

    • 8 respostas
  • Marko Smith

    Quão grande deve ser o mysql innodb_buffer_pool_size?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    restaurar a tabela do arquivo .frm e .ibd?

    • 10 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Como selecionar a primeira linha de cada grupo?

    • 6 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    bernd_k Quando devo usar uma restrição exclusiva em vez de um índice exclusivo? 2011-01-05 02:32:27 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve