Dziennik transakcji bazy danych jest pełny

109

Mam długotrwały proces, który wstrzymuje otwartą transakcję przez cały czas.

Nie mam kontroli nad sposobem, w jaki to jest wykonywane.

Ponieważ transakcja jest otwarta przez cały czas, po wypełnieniu dziennika transakcji SQL Server nie może zwiększyć rozmiaru pliku dziennika.

Więc proces kończy się niepowodzeniem z powodu błędu "The transaction log for database 'xxx' is full".

Próbowałem temu zapobiec, zwiększając rozmiar pliku dziennika transakcji we właściwościach bazy danych, ale pojawia się ten sam błąd.

Nie jestem pewien, czego powinienem spróbować dalej. Proces trwa kilka godzin, więc nie jest łatwo grać metodą prób i błędów.

Jakieś pomysły?

Jeśli ktoś jest zainteresowany, procesem jest import organizacji Microsoft Dynamics CRM 4.0.

Jest dużo miejsca na dysku, logujemy się w prostym trybie logowania i utworzyliśmy kopię zapasową dziennika przed rozpoczęciem procesu.

- = - = - = - = - AKTUALIZACJA - = - = - = - = -

Dziękuję wszystkim za dotychczasowe komentarze. Oto, co skłoniło mnie do przekonania, że ​​dziennik nie wzrośnie z powodu otwartej transakcji:

Otrzymuję następujący błąd ...

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

Więc postępując zgodnie z tą radą poszedłem do „ log_reuse_wait_desc column in sys.databases” i to miało wartość „ ACTIVE_TRANSACTION”.

Według Microsoft: http://msdn.microsoft.com/en-us/library/ms345414(v=sql.105).aspx

To oznacza co następuje:

Transakcja jest aktywna (wszystkie modele odzyskiwania). • Na początku tworzenia kopii zapasowej dziennika może istnieć długoterminowa transakcja. W takim przypadku zwolnienie miejsca może wymagać kolejnej kopii zapasowej dziennika. Aby uzyskać więcej informacji, zobacz „Długoterminowe aktywne transakcje” w dalszej części tego tematu.

• Transakcja jest odroczona (tylko SQL Server 2005 Enterprise Edition i nowsze wersje). Transakcja odroczona jest faktycznie transakcją aktywną, której wycofanie jest zablokowane z powodu niedostępnego zasobu. Aby uzyskać informacje o przyczynach odroczonych transakcji i sposobach ich przenoszenia ze stanu odroczonego, zobacz Transakcje odroczone.

Czy coś źle zrozumiałem?

- = - = - = - AKTUALIZACJA 2 - = - = - = -

Właśnie rozpoczęto proces, ustawiając początkowy rozmiar pliku dziennika na 30 GB. To zajmie kilka godzin.

- = - = - = - Ostateczna AKTUALIZACJA - = - = - = -

Problem był faktycznie spowodowany tym, że plik dziennika zajmował całe dostępne miejsce na dysku. W ostatniej próbie zwolniłem 120 GB i nadal je wykorzystywałem i ostatecznie się nie udało.

Nie zdawałem sobie sprawy, że dzieje się to wcześniej, ponieważ gdy proces był wykonywany w nocy, wycofywał się po niepowodzeniu. Tym razem udało mi się sprawdzić rozmiar pliku dziennika przed wycofaniem.

Dziękuję wszystkim za wkład.

Jimbo
źródło
re „... i utworzono kopię zapasową dziennika” .... jeśli baza danych jest w trybie prostym, nie będzie można wykonać kopii zapasowej dziennika, kopie zapasowe dziennika nie mają zastosowania w trybie prostym. Czy to jest rejestrowane zbiorczo?
SqlACID,
1
Zrobiłem kopię zapasową całej bazy danych i zmniejszyłem ją, co spowodowało zmniejszenie dziennika do 1 MB. Następnie zwiększyłem początkowo rozmiar pliku dziennika do 20 GB, a teraz do 30 GB.
Jimbo,

Odpowiedzi:

19

Czy to jednorazowy skrypt, czy regularnie występująca praca?

W przeszłości do specjalnych projektów, które tymczasowo wymagały dużej ilości miejsca na plik dziennika, utworzyłem drugi plik dziennika i uczyniłem go ogromnym. Po zakończeniu projektu usunęliśmy dodatkowy plik dziennika.

Mike Henderson
źródło
Nie powiedziałbym, że to jednorazowa praca, ale rzadko kiedy musimy to robić. Nie utworzyłem drugiego pliku dziennika, ale zwiększyłem początkowy rozmiar mojego obecnego pliku dziennika do 30 GB. Podczas mojego ostatniego uruchomienia był ustawiony na 20 GB i nadal nie działał.
Jimbo,
Czy posiadanie drugiego pliku dziennika byłoby w jakiś sposób lepsze niż posiadanie jednego dużego, biorąc pod uwagę, że mam tylko jeden dysk do pracy?
Jimbo,
Jak sobie teraz przypominam, dodatkowy plik umożliwiał nam dostęp do innego, większego dysku.
Mike Henderson,
2
Jak duże są importowane dane? Jeśli importujesz 30 GB danych, plik dziennika może być co najmniej tak duży.
Mike Henderson,
3
Rozmiar dziennika jest kluczem. Bieżące zadanie znów się nie powiodło i nie mogłem uwierzyć własnym oczom, gdy zobaczyłem rozmiar pliku dziennika w momencie, w którym się nie powiodło. Przetworzył tylko połowę kont i miał już 53 GB. Wygląda na to, że będę musiał wyczyścić gdzieś w pobliżu kolejne 60-70 GB, aby móc ukończyć ten proces.
Jimbo,
95

Aby rozwiązać ten problem, zmień Model odzyskiwania na Prosty, a następnie zmniejsz dziennik plików

1. Właściwości bazy danych> Opcje> Model odzyskiwania> Proste

2. Zadania bazy danych> Zmniejsz> Pliki> Dziennik

Gotowe.

Następnie sprawdź rozmiar pliku dziennika db w Właściwości bazy danych> Pliki> Pliki bazy danych> Ścieżka

Aby sprawdzić pełny dziennik serwera sql: otwórz przeglądarkę plików dziennika w SSMS> Baza danych> Zarządzanie> Dzienniki SQL Server> Bieżące

user3774600
źródło
10
Nie, to nie rozwiązuje problemu. Problem polegał na tym, że plik dziennika rósł podczas długotrwałego procesu, aż zabrakło miejsca na dysku. Zostało to poprawione przez tymczasowe przeniesienie pliku dziennika na inny dysk, na którym było 1 TB wolnego miejsca. Nie można zmniejszyć pliku dziennika, gdy długo działający proces - czyli wstrzymanie otwartej transakcji - jest w toku. Ten proces był wyłącznie odpowiedzialny za wzrost pliku.
Jimbo,
Jak już powiedział @Jimbo, nie rozwiązuje to problemu OP. Może zwolnić trochę obecnie nieużywanego miejsca, ale gdy tylko długa transakcja zostanie ponownie uruchomiona, miejsce zostanie ponownie zajęte (i prawdopodobnie zakończy się niepowodzeniem nawet wcześniej)
Marcel
Idealny! Dzięki!
Yuri Monteiro
To nie rozwiązało problemu. Mój dziennik ma tylko 500 bajtów. Myślę, że ten problem zaczął się po wczorajszym wykonaniu kopii zapasowej.
Ricardo França,
Jest to zdecydowanie rozwiązanie, jeśli masz jeszcze kilka megabajtów do wykorzystania na pełnym dysku.
Steve Bauman
36

Kiedyś miałem ten błąd i okazało się, że na dysku twardym serwera zabrakło miejsca.

PretoriaCoder
źródło
1
Przeczytaj aktualizacje OP. Okazało się, że to był problem.
Colm
18

Czy dla pliku dziennika włączono opcję Włącz automatyczne i nieograniczony wzrost plików? Możesz je edytować przez SSMS w „Właściwości bazy danych> Pliki”

Ross McNab
źródło
Tak. Jest ustawiony na autorosowanie o 10%, bez ograniczeń. Problem polega na tym, że autogrow nie działa, gdy istnieje otwarta transakcja.
Jimbo,
1
Czy masz pojęcie, jak duża będzie transakcja? spróbuj ustawić rozmiar dziennika transakcji większy niż to oszacowanie, tak czy inaczej, jeśli alokacja dysku nie jest problemem, przydziel na początku dużo miejsca na dane i dziennik. Poprawia wydajność. Nie zwiększaj automatycznie o 10% , zrób to o kilka GB, więc wydajność będzie wystarczająco dobra.
Luis LL,
3
SQL Server automatycznie zwiększy dziennik podczas transakcji, jeśli będzie potrzebował więcej miejsca do zakończenia tej transakcji.
Ross McNab,
Cześć Ross, przedstawiłem swoją logikę, zgodnie z którą myślę, że otwarta transakcja zapobiega wzrostowi aktualizacji pytania. Czy moje rozumowanie jest błędne?
Jimbo,
1
@Jimbo SQL Server nie wymaga, abyś był zarezerwowany. Jeśli masz autogrow, SQL Server robi to autogrow podczas transakcji. Wystarczająco duży może zaoszczędzić dużo czasu, ale nie powinien wpływać na proces.
Luis LL,
10

Jest to podejście starej szkoły, ale jeśli wykonujesz iteracyjną aktualizację lub operację wstawiania w SQL, coś, co działa przez długi czas, dobrym pomysłem jest okresowe (programowe) wywoływanie „punktu kontrolnego”. Wywołanie „punktu kontrolnego” powoduje, że SQL zapisuje na dysku wszystkie te zmiany tylko w pamięci (nazywane są brudnymi stronami) i elementy przechowywane w dzienniku transakcji. Powoduje to okresowe czyszczenie dziennika transakcji, zapobiegając w ten sposób problemom takim jak ten opisany.

Brian
źródło
1
Niestety nie mam kontroli nad sposobem wykonywania tego procesu. Dynamics CRM to aplikacja firmy Microsoft, a proces importu organizacji jest częścią tej aplikacji.
Jimbo,
1

Poniższe czynności spowodują obcięcie dziennika.

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
źródło
4
Hej Pinal, ta funkcja została całkowicie usunięta z SQL Server 2008 i nowszych wersji: brentozar.com/archive/2009/08/…
Conor
3
W nowszych wersjach spróbuj BACKUP LOG <myDB> TO DISK = N'NUL: '
HansLindgren
1

Jeśli model odzyskiwania bazy danych jest pełny i nie masz planu konserwacji kopii zapasowej dziennika, zostanie wyświetlony ten błąd, ponieważ dziennik transakcji zostanie zapełniony z powodu LOG_BACKUP.

Zapobiegnie to wszelkim działaniom na tej bazie danych (np. Zmniejszeniu), a aparat bazy danych programu SQL Server zgłosi błąd 9002.

Aby przezwyciężyć to zachowanie, radzę sprawdzić to. Dziennik transakcji dla bazy danych „SharePoint_Config” jest pełny ze względu na LOG_BACKUP, który zawiera szczegółowe instrukcje rozwiązania problemu.

Jihan
źródło
0

Napotkałem błąd: „Dziennik transakcji bazy danych '...' jest pełny z powodu 'ACTIVE_TRANSACTION' podczas usuwania starych wierszy z tabel mojej bazy danych w celu zwolnienia miejsca na dysku. Zrozumiałem, że ten błąd wystąpiłby, gdyby liczba wierszy była w moim przypadku wartość do usunięcia była większa niż 1000000. Zamiast używać 1 instrukcji DELETE, podzieliłem zadanie usuwania za pomocą instrukcji DELETE TOP (1000000) ....

Na przykład:

zamiast używać tego stwierdzenia:

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

używając wielokrotnie następującego oświadczenia:

DELETE TOP(1000000) FROM Vt30 WHERE Rt < DATEADD(YEAR, -1, GETDATE())
Linh Dao
źródło
0

Mój problem został rozwiązany dzięki wielokrotnemu wykonywaniu ograniczonych operacji usuwania, takich jak

Przed

DELETE FROM TableName WHERE Condition

Po

DELETE TOP(1000) FROM TableName WHERECondition
Amir Astaneh
źródło
-1

Odpowiedzią na pytanie nie jest usuwanie wierszy z tabeli, ale miejsce zajmowane w tempDB z powodu aktywnej transakcji. zdarza się to głównie wtedy, gdy jest uruchamiane scalanie (upsert), w którym próbujemy wstawić aktualizację i usunąć transakcje. Jedyną opcją jest upewnienie się, że DB jest ustawiony na prosty model odzyskiwania, a także zwiększenie pliku do maksymalnej przestrzeni (Dodaj inną grupę plików). Chociaż ma to swoje zalety i wady, są to jedyne opcje.

Inną opcją, którą masz, jest podzielenie scalania (upsert) na dwie operacje. jeden, który wstawia, a drugi aktualizuje i usuwa.

Rohit Reddy
źródło
Jeśli przeczytasz pytanie, wiesz, że baza danych była już w prostym trybie odzyskiwania, gdy to się działo. To nie pomaga, gdy masz jedną długo trwającą otwartą transakcję. Plik rośnie, dopóki transakcja nie zostanie zatwierdzona lub wycofana. Przeczytaj pierwszą linię pytania „Mam długotrwały proces, który wstrzymuje transakcję przez cały czas”.
Jimbo,
-1

Spróbuj tego:

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 

Mam nadzieję, że to pomoże.

Saadat
źródło
To była jedna z pierwszych rzeczy, których podjęto próbę, a nawet wspomniano o tym w tekście pytania. Nie rozwiązuje to problemu pojedynczej otwartej transakcji wypełniającej dziennik i zajmującej całe dostępne miejsce na dysku. Cały ten proces odbywał się w trybie prostym. Jednak należysz do wielu osób, które udzieliły dokładnej odpowiedzi, nie czytając pytania ...
Jimbo,
-1

Oto mój kod bohatera. Zmierzyłem się z tym problemem. I użyj tego kodu, aby to naprawić.

 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
źródło
Prosimy o umieszczanie odpowiedzi zawsze w kontekście, a nie tylko wklejanie kodu. Więcej informacji znajdziesz tutaj .
gehbiszumeis
-1

Spróbuj tego:

Jeśli to możliwe, uruchom ponownie usługi MSSQLSERVER i SQLSERVERAGENT .

Lemraj
źródło