locked
BD em [Single User] apresenta problema ao ser atualizado RRS feed

  • Pergunta

  • Olá Pessoal,

    Tenho uma aplicação em Delphi(DbExpress) com SQL Server 2000/2005/2008.
    Tenho outro exe que atualiza o BD, setando o database para single user e atualizando tabelas/procedures/etc.
    Qdo um user tenta acessar o exe da aplicação durante a atualização, o mesmo é bloqueado porém acontece erro na atualização.

    Segue os comandos e erros que estã ocorrendo:

    [mato conexões antes se necessário]

    kill @Spid

    [Seto para single user]

    ALTER DATABASE [NomeInstanciaBD] SET SINGLE_USER WITH NO_WAIT

    [Executo vários scripts para atualizar as tabelas/procedures/etc]

    if exists (select top 1 1 from sysobjects where id = object_id('dbo.f_ItemPrincipalPlano') and sysstat & 0xf = 0)
       drop function dbo.f_ItemPrincipalPlano
    go
    Create function dbo.f_ItemPrincipalPlano( @CodPlDia char(12) ) RETURNS varchar(500) As
    Begin
        ...
    End;

    [Aleatoriamente, recebo a msg de erro e a procedure não é criada]

    Database 'nomeBanco' is already open and can only have one user at a time.

     

     

    Será que alguém passou por isso ou tem alguma idéia do que estou fazendo errado?
    Qualquer dica é bem vinda ...

     

    • Movido Gustavo Maia Aguiar quinta-feira, 4 de agosto de 2011 12:53 (De:SQL Server - Desenvolvimento Geral)
    quinta-feira, 4 de agosto de 2011 12:01

Respostas

  • Bom Dia,

    Se você faz a gestão de permissões adequadamente (e o usuário da aplicação não é db_owner), você pode fazer o seguinte:

    - Mudar a base para Restricted User
    - Conectar com outro usuário (que seja owner)
    - Aplicar os scripts necessários
    - Retirar a base de Restricted User

    Não recomendo fazer o KILL manualmente. Você pode fazer tudo em um passo só (desde que você não esteja conectado no banco):

    ALTER DATABASE Banco SET SINGLE_USER WITH ROLLBACK IMMEDIATE

    O erro provavelmente acontece, porque entre o banco ficar em SINGLE User e você conectar, alguém chegou primeiro. Esse problema não aconteceria na situação anterior, pois, se o usuário da aplicação não for owner ele não conseguirá conectar-se.

    [ ]s,

    Gustavo Maia Aguiar
    http://gustavomaiaaguiar.wordpress.com


    Classifique as respostas. O seu feedback é imprescindível
    quinta-feira, 4 de agosto de 2011 12:49

Todas as Respostas

  • Bom Dia,

    Se você faz a gestão de permissões adequadamente (e o usuário da aplicação não é db_owner), você pode fazer o seguinte:

    - Mudar a base para Restricted User
    - Conectar com outro usuário (que seja owner)
    - Aplicar os scripts necessários
    - Retirar a base de Restricted User

    Não recomendo fazer o KILL manualmente. Você pode fazer tudo em um passo só (desde que você não esteja conectado no banco):

    ALTER DATABASE Banco SET SINGLE_USER WITH ROLLBACK IMMEDIATE

    O erro provavelmente acontece, porque entre o banco ficar em SINGLE User e você conectar, alguém chegou primeiro. Esse problema não aconteceria na situação anterior, pois, se o usuário da aplicação não for owner ele não conseguirá conectar-se.

    [ ]s,

    Gustavo Maia Aguiar
    http://gustavomaiaaguiar.wordpress.com


    Classifique as respostas. O seu feedback é imprescindível
    quinta-feira, 4 de agosto de 2011 12:49
  • Valeu pela dica Gustavo,

    Mas eu acho que não me expressei bem.

    Tenho 2 exe ("aplicacao.exe" e "atualizador.exe"). Quando executo o atualizador, crio uma interface amigável que permite ao administrador ver as conexões e optar pelo Kill ou abortar o processo.

    O problema é que após iniciar a atualização(pelo atualizador.exe) e colocar o BD em Single User, se um usuário tentar acessar a aplicacao.exe(existe um tratamento para verificar se o BD esta single user e terminar a aplicaçao.exe), no atualizador.exe acontece o erro "Database 'nomeBanco' is already open and can only have one user at a time.".

    Acredito que se eu seguir a sua sugestão, daria o mesmo problema, pois se um usuário tentar acessar a aplicacao.exe durante a atualização vai acontecer o mesmo ambiente de erro que estou tendo agora.

    O que vc acha? Tem outras sugestões?

    quinta-feira, 4 de agosto de 2011 14:59
  • Bueno,

     

    Nunca vi algo assim, e teoricamente quando o banco de dados esta em single-user e ja possui um usuario, outros não irão se conectar, todo caso, qual o nivel de permissao deste usuario da aplicação? é maior que o do usuario de atualização? Como é feita essa verificação se ja existe alguem na base enquanto esta atualizando?


    Fabrizzio A. Caputo
    Certificações:
    Oracle OCA 11g
    MCITP SQL Server 2008 Implementation and Maintenance
    MCITP SQL Server 2008 Developer
    Blog Pessoal: www.fabrizziocaputo.wordpress.com
    Blog Empresa: www.tripletech.com.br/blog
    Twitter: @FabrizzioCaputo
    Email: fabrizzio.antoniaci@gmail.com
    quinta-feira, 4 de agosto de 2011 15:07
    Moderador
  • Olá Fabrizzio,

    O usuário do Atualizador é SA, o da Aplicacao é simples(db_owner) podendo ser o SA também.

    Verifico se existe usuário ativo através do [sp_who].

    Após setar o BD com [Single User] ninguém consegue conectar. Porém acontece o erro "Database 'nomeBanco' is already open and can only have one user at a time." ao atualizar as procedures do BD(ou seja, acontece no Atualizador.exe).

    Detalhe: Eu apago e recrio todas as procedures, porém somente algumas dão o erro. É como se no intervalo de tempo que tenta acessar a "Aplicacao.exe" com o BD em [Single User]  acontece algo no Banco que interfere na atualização/criação da procedure. E não é erro na programaçao da procedure, pois o erro acontece aleatoriamente cada vez que executo o atualizador e testo esse caso.

    quinta-feira, 4 de agosto de 2011 16:48
  • Oi Bueno,

    Eu ainda estou apostando que há alguma outra conexão no momento em que você tenta atualização. Seria possível confirmar se fosse feita uma consulta por fora (via SSMS por exemplo), na sys.sysprocesses e verificar quem está conectado.

    A minha solução não incorreria nesse problema, uma vez que a opção Restricted User apenas restringe o banco a usuários DBO e Sysadmin e não a um único usuário (Single User). Se aplicacao.exe não usa um usuário owner da base, então essa abordagem funcionaria perfeitamente, pois, por mais que aplicacao.exe tentasse, ela não conseguiria dispensando inclusive a verificação do estado do banco de dados. Quando atualizador.exe concluísse, poderia retirar a base de restricted user para que aplicacao.exe voltasse a funcionar.

    [ ]s,

    Gustavo Maia Aguiar
    http://gustavomaiaaguiar.wordpress.com


    Classifique as respostas. O seu feedback é imprescindível
    quinta-feira, 4 de agosto de 2011 16:50