O log de transações do banco de dados está cheio

108

Tenho um processo demorado que mantém uma transação aberta por toda a duração.

Não tenho controle sobre a maneira como isso é executado.

Como uma transação é mantida aberta por toda a duração, quando o log de transações é preenchido, o SQL Server não pode aumentar o tamanho do arquivo de log.

Portanto, o processo falha com o erro "The transaction log for database 'xxx' is full".

Tentei evitar isso aumentando o tamanho do arquivo de log de transações nas propriedades do banco de dados, mas recebo o mesmo erro.

Não tenho certeza do que devo tentar a seguir. O processo dura várias horas, por isso não é fácil jogar por tentativa e erro.

Alguma ideia?

Se alguém estiver interessado, o processo é uma importação de organização em Microsoft Dynamics CRM 4.0.

Há bastante espaço em disco, temos o log no modo de registro simples e fizemos o backup do log antes de iniciar o processo.

- = - = - = - = - ATUALIZAÇÃO - = - = - = - = -

Obrigado a todos pelos comentários até agora. O seguinte é o que me levou a acreditar que o log não cresceria devido à transação aberta:

Eu estou recebendo o seguinte erro...

Import Organization (Name=xxx, Id=560d04e7-98ed-e211-9759-0050569d6d39) failed with Exception:
System.Data.SqlClient.SqlException: The transaction log for database 'xxx' is full. To find out why space in the log cannot be reused, see the log_reuse_wait_desc column in sys.databases

Seguindo esse conselho, fui para " log_reuse_wait_desc column in sys.databases" e ele continha o valor " ACTIVE_TRANSACTION".

De acordo com a Microsoft: http://msdn.microsoft.com/en-us/library/ms345414(v=sql.105).aspx

Isso significa o seguinte:

Uma transação está ativa (todos os modelos de recuperação). • Uma transação de longa duração pode existir no início do backup de log. Nesse caso, a liberação de espaço pode exigir outro backup de log. Para obter mais informações, consulte "Transações ativas de longa duração", posteriormente neste tópico.

• Uma transação é adiada (SQL Server 2005 Enterprise Edition e versões posteriores apenas). Uma transação adiada é efetivamente uma transação ativa cujo rollback está bloqueado devido a algum recurso indisponível. Para obter informações sobre as causas das transações adiadas e como retirá-las do estado adiado, consulte Transações adiadas.

Eu não entendi alguma coisa?

- = - = - = - ATUALIZAÇÃO 2 - = - = - = -

Acabei de iniciar o processo com o tamanho do arquivo de log inicial definido para 30 GB. Isso levará algumas horas para ser concluído.

- = - = - = - ATUALIZAÇÃO Final - = - = - = -

O problema era realmente causado pelo arquivo de log consumindo todo o espaço disponível em disco. Na última tentativa, liberei 120 GB e ainda usei tudo e acabou falhando.

Não percebi que isso estava acontecendo antes porque, quando o processo estava em execução durante a noite, ele voltava em caso de falha. Desta vez, consegui verificar o tamanho do arquivo de log antes do rollback.

Obrigado a todos por sua contribuição.

Jimbo
fonte
re "... e tenha feito backup do log" .... se o banco de dados estiver no modo Simples, você não poderá fazer backup do log, os backups de log não são aplicáveis ​​para o modo simples. É registrado em massa?
SqlACID
1
Fiz backup de todo o banco de dados e o encolhi, o que resultou na redução do log para 1 MB. Em seguida, aumentei o tamanho do arquivo de log inicialmente para 20 GB e agora para 30 GB.
Jimbo
Postagem relacionada - TempDB Log Space e ACTIVE_TRANSACTION
RBT

Respostas:

19

Este é um script único ou um trabalho que ocorre regularmente?

No passado, para projetos especiais que requerem temporariamente muito espaço para o arquivo de log, criei um segundo arquivo de log e o tornei enorme. Assim que o projeto estiver concluído, removemos o arquivo de log extra.

Mike Henderson
fonte
Eu não diria que é um trabalho único, mas é raro termos que fazer isso. Não criei um segundo arquivo de log, mas aumentei o tamanho inicial do meu arquivo de log atual para 30 GB. Durante minha última execução, ele foi definido para 20 GB e ainda falhou.
Jimbo
Ter um segundo arquivo de log seria melhor do que ter um grande, já que só tenho uma unidade para trabalhar?
Jimbo
Pelo que me lembro agora, o arquivo adicional principalmente nos permitiu acessar outra unidade maior.
Mike Henderson
2
Qual é o tamanho dos dados sendo importados? Se você estiver importando 30 GB de dados, seu arquivo de log pode precisar ser pelo menos tão grande.
Mike Henderson
3
O tamanho do log é a chave. A tarefa atual falhou novamente e eu não pude acreditar nos meus olhos quando vi o tamanho do arquivo de log no ponto em que ele falhou. Ele processou apenas metade das contas e já estava com 53 GB. Parece que terei que limpar em algum lugar próximo a outros 60-70 GB para poder concluir este processo.
Jimbo
95

Para corrigir esse problema, altere o modelo de recuperação para Simples e depois diminua o registro de arquivos

1. Propriedades do banco de dados> Opções> Modelo de recuperação> Simples

2. Tarefas de banco de dados> Reduzir> Arquivos> Log

Feito.

Em seguida, verifique o tamanho do arquivo de log do banco de dados em Propriedades do banco de dados> Arquivos> Arquivos do banco de dados> Caminho

Para verificar o log do sql server completo: abra o Log File Viewer em SSMS> Database> Management> SQL Server Logs> Current

user3774600
fonte
10
Não, isso não resolve o problema. O problema era que o arquivo de log cresceu durante um processo de longa execução até ficar sem espaço em disco. Ele foi corrigido movendo temporariamente o arquivo de log para outra unidade que tinha 1 TB de espaço disponível. Você não pode reduzir o arquivo de log enquanto um processo de longa execução - que está mantendo uma transação aberta - está em andamento. Esse processo foi o único responsável pelo crescimento do arquivo.
Jimbo,
Como o @Jimbo já disse, isso não resolve o problema do OP. Isso pode liberar algum espaço não utilizado no momento, mas assim que uma transação longa for executada novamente, o espaço será ocupado novamente (e provavelmente falhará ainda mais cedo)
Marcel
Perfeito! Obrigado!
Yuri Monteiro
Isso não resolveu o problema. Meu log tem apenas 500 bytes. Acho que esse problema começou depois que fiz um backup ontem.
Ricardo França
Esta é definitivamente a solução se você tiver alguns megabytes sobrando na unidade completa.
Steve Bauman
36

Eu tive esse erro uma vez e acabou sendo o disco rígido do servidor que ficou sem espaço em disco.

PretoriaCoder
fonte
1
Leia as atualizações do OP. Este acabou sendo o problema.
Colm
18

Você tem Ativar Aumento Automático e Crescimento Irrestrito de Arquivo ativados para o arquivo de log? Você pode editá-los via SSMS em "Propriedades do banco de dados> Arquivos"

Ross McNab
fonte
Sim. Está definido para crescimento automático em 10%, sem restrições. O problema é que o crescimento automático não funcionará enquanto houver uma transação aberta.
Jimbo
1
Você tem ideia do tamanho da transação? tente definir o tamanho do log de transações maior do que essa estimativa; de qualquer maneira, se a alocação de disco não for um problema, aloque no início bastante espaço para dados e log também. Além disso, melhora o desempenho. Não cresça automaticamente em 10% , faça-o em alguns poucos GB, para que o desempenho seja bom o suficiente.
Luis LL
3
O SQL Server aumentará automaticamente o log durante uma transação se precisar de mais espaço para concluir essa transação.
Ross McNab
Olá, Ross. Forneci minha lógica para pensar que a transação aberta está impedindo o crescimento de uma atualização da pergunta. Estou incorreto em meu raciocínio?
Jimbo
1
@Jimbo SQL Server não exige que você o tenha reservado. Se você tiver crescimento automático, o SQL Server fará o crescimento automático durante a transação. Ter um tamanho suficiente pode economizar muito tempo, mas não deve afetar o processo.
Luis LL
10

Esta é uma abordagem da velha escola, mas se você estiver realizando uma atualização iterativa ou operação de inserção em SQL, algo que é executado por um longo tempo, é uma boa ideia periodicamente (programaticamente) chamar "checkpoint". Chamar "ponto de verificação" faz com que o SQL grave no disco todas as alterações apenas de memória (páginas sujas, são chamadas) e itens armazenados no log de transações. Isso tem o efeito de limpar o log de transações periodicamente, evitando problemas como o descrito.

Brian
fonte
1
Infelizmente, não tenho controle sobre a forma como o processo é executado. O Dynamics CRM é um aplicativo da Microsoft e o processo de importação da organização faz parte desse aplicativo.
Jimbo
1

O seguinte truncará o log.

USE [yourdbname] 
GO

-- TRUNCATE TRANSACTION LOG --
DBCC SHRINKFILE(yourdbname_log, 1)
BACKUP LOG yourdbname WITH TRUNCATE_ONLY
DBCC SHRINKFILE(yourdbname_log, 1)
GO

-- CHECK DATABASE HEALTH --
ALTER FUNCTION [dbo].[checker]() RETURNS int AS BEGIN  RETURN 0 END
GO
Pinal
fonte
4
Ei, Pinal, esta funcionalidade foi removida completamente do SQL Server 2008 e superior: brentozar.com/archive/2009/08/…
Conor
3
Com versões posteriores, tente BACKUP LOG <myDB> TO DISK = N'NUL: '
HansLindgren
1

Se o seu modelo de recuperação de banco de dados estiver cheio e você não tiver um plano de manutenção de backup de log, receberá este erro porque o log de transações fica cheio devido a LOG_BACKUP.

Isso impedirá qualquer ação neste banco de dados (por exemplo, reduzir) e o Mecanismo de banco de dados do SQL Server gerará um erro 9002.

Para superar esse comportamento, aconselho você a verificar isso O log de transações do banco de dados 'SharePoint_Config' está cheio devido ao LOG_BACKUP que mostra as etapas detalhadas para resolver o problema.

Jihan
fonte
0

Encontrei o erro: "O log de transações do banco de dados '...' está cheio devido a 'ACTIVE_TRANSACTION' ao excluir linhas antigas das tabelas do meu banco de dados para liberar espaço em disco. Percebi que esse erro ocorreria se o número de linhas para ser excluído era maior que 1000000 no meu caso. Então, em vez de usar 1 instrução DELETE, eu dividi a tarefa de exclusão usando DELETE TOP (1000000) .... instrução.

Por exemplo:

em vez de usar esta declaração:

DELETE FROM Vt30 WHERE Rt < DATEADD(YEAR, -1, GETDATE())

usando a seguinte declaração repetidamente:

DELETE TOP(1000000) FROM Vt30 WHERE Rt < DATEADD(YEAR, -1, GETDATE())
Linh Dao
fonte
0

Meu problema foi resolvido com a execução múltipla de exclusões limitadas como

Antes

DELETE FROM TableName WHERE Condition

Depois de

DELETE TOP(1000) FROM TableName WHERECondition
Amir Astaneh
fonte
-1

A resposta à pergunta não é excluir as linhas de uma tabela, mas é o espaço do tempDB que está sendo ocupado devido a uma transação ativa. isso acontece principalmente quando há uma mesclagem (upsert) sendo executada onde tentamos inserir, atualizar e excluir as transações. A única opção é certificar-se de que o banco de dados está configurado para o modelo de recuperação simples e também aumentar o arquivo para o espaço máximo (adicionar outro grupo de arquivos). Embora isso tenha suas próprias vantagens e desvantagens, essas são as únicas opções.

A outra opção que você tem é dividir a fusão (upsert) em duas operações. um que faz a inserção e outro que faz a atualização e exclusão.

Rohit Reddy
fonte
Se você leu a pergunta, você sabe que o DB já estava em modo de recuperação simples no momento em que isso acontecia. Isso não ajuda quando você tem uma transação aberta de longa duração. O arquivo continua a crescer até que a transação seja confirmada ou revertida. Leia a primeira linha da pergunta "Tenho um processo demorado que mantém uma transação aberta por toda a duração."
Jimbo
-1

Experimente isto:

USE YourDB;  
GO  
-- Truncate the log by changing the database recovery model to SIMPLE.  
ALTER DATABASE YourDB
SET RECOVERY SIMPLE;  
GO  
-- Shrink the truncated log file to 50 MB.  
DBCC SHRINKFILE (YourDB_log, 50);  
GO  
-- Reset the database recovery model.  
ALTER DATABASE YourDB
SET RECOVERY FULL;  
GO 

Espero que ajude.

Saadat
fonte
Esta foi uma das primeiras coisas que tentámos e até é mencionada no texto da pergunta. Isso não resolve o problema de uma única transação aberta preencher o log e usar todo o espaço em disco disponível. Todo esse processo ocorreu de modo simples. Porém, você é uma das muitas pessoas que ofereceu esta resposta exata sem ter lido a pergunta ...
Jimbo
-1

Aqui está o meu código de herói. Eu enfrentei esse problema. E use este código para corrigir isso.

 USE master;

    SELECT 
        name, log_reuse_wait, log_reuse_wait_desc, is_cdc_enabled 
    FROM 
        sys.databases 
    WHERE 
        name = 'XX_System';

    SELECT DATABASEPROPERTYEX('XX_System', 'IsPublished');


    USE XX_System;
    EXEC sp_repldone null, null, 0,0,1;
    EXEC sp_removedbreplication XX_System;


    DBCC OPENTRAN;
    DBCC SQLPERF(LOGSPACE);
    EXEC sp_replcounters;



    DBCC SQLPERF(LOGSPACE);
narawit1601
fonte
Por favor, coloque sua resposta sempre no contexto, em vez de apenas colar o código. Veja aqui para mais detalhes.
gehbiszumeis
-1

Experimente isto:

Se possível reinicie os serviços MSSQLSERVER e SQLSERVERAGENT .

Lemraj
fonte