siquellando

...scoperte e considerazioni Sql di uno sviluppista
(un po' sviluppatore e un po' sistemista)

Il recovery model SIMPLE

In merito al recovery model SIMPLE spesso girano dubbi e spesso capita di sentirsi chiedere cosa logga e se le sue dimensioni crescono  e perche' crescono  e quando si "sgonfia" etc etc. Sperando di fare cosa utile in questo post provero' a fare un po' di chiarezza in merito...

Innazitutto chiariamo che una modalita' di logging SIMPLE non significa che non loggo ... Tutt'altro: SIMPLE significa solo che il transaction log non potra' essere utilizzato in fase di restore (infatti in questa modalita' non e' concesso il backup del log), ma che comunque viene assicurata tutta l'attivita' relativa alla gestione delle transazioni ... e ci mancherebbe che non lo facesse !!!! Big Smile

Pertanto, anche in questa modalita', il transaction log conterra' tutte le informazioni necessarie a Sql per poter gestire un eventuale roll back. Questo comporta che il file di log avra' una dimensione tale da memorizzare tutte le transazioni non ancora committate o, piu' precisamente, conterra' "almeno" tutte le transazioni avvenute a partire dalla piu' vecchia presente ancora non committata.

Per questa ragione, in presenza di transazioni ricche di dati, anche in modalita' SIMPLE il file di log crescera' e potrebbe assumere dimensioni anche elevate.

La differenza con le altre due modalita di recovery (FULL e BULK_INSERT) risiede nel fatto che, man mano che le transazioni vengono committate lo spazio a loro associato viene riutilizzato per memorizzare nuove transazioni.[per dirla piu' correttamente viene riutilizzato lo spazio associato alle transazioni antecedenti alla piu' vecchia non committata]. Questo in FULL e BULK_INSERT avviene dopo il backup del log.

 

Nella modalita' SIMPLE periodicamente e con una frequenza legata alle dimensioni del file di log e al suo grado di riempimento, viene verificata la posizione della transazione attiva piu' vecchia e viene marcato come riutilizzabile lo spazio del log allocato a tutte le transazioni antecedenti a questa. Tale attivita' prende il nome di Troncamento (truncation) del log.

Il Log truncation e' un attivita' di tipo logico: ad essa non e' associata una riduzione fisica del log.

La diminuzione del file di log e' legata all'attivita' di Shrink che, se non e' abilitata tramite l'opzione AUTO_SHRINK ON (cosa da non fare MAI Angry), avverra' solo dietro un preciso comando (ad esempio un DBCC SHRINKDATABASE).

Detto cio' bisogna ricordare che il recovery model SIMPLE, visto che non consente il recovery tramite log, andrebbe usato raramente: di fatto solo con DB in read only o di test... Averlo in produzione significa sapere che, in caso di failure, verranno perse tutte le transazioni intercorse dall'ultimo backup (full o differenziale) cosa che ritengo sia accettabile in ben poche situazioni....

 

Di seguito, per i curiosi, un po' di codice "pronto all'uso" per vedere la crescita del file di log in modalita' SIMPLE.

Ciao.

-- Test sul recovery model Simple

USE [master]

GO

-- Creazione db e tabelle di test

-- Il file di log e' VOLUTAMENTE inizializzato piccolo con bassa crescita

-- per valutarne l'aumento di dimensioni

IF EXISTS (SELECT name FROM sys.databases WHERE name = N'TestRecoverySimple')

DROP DATABASE TestRecoverySimple

GO

 

CREATE DATABASE TestRecoverySimple ON PRIMARY

( NAME = N'TestRecoverySimple', FILENAME = N'C:\Temp\TestRecoverySimple.mdf' ,

SIZE = 20480KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1MB )

LOG ON

( NAME = N'TestRecoverySimple_log', FILENAME = N'C:\Temp\TestRecoverySimple_log.ldf' ,

SIZE = 1MB , MAXSIZE = UNLIMITED, FILEGROWTH = 1MB)

GO

-- setto il recovery model a SIMPLE

alter database TestRecoverySimple set recovery Simple;

GO

-- disabilito l'auto shrink del DB(da non abilitare mai)

alter database TestRecoverySimple set Auto_Shrink OFF;

GO

 

--- Creo la tabella di test

use TestRecoverySimple

GO

create table BigInsert (Id int identity(1,1),

Data datetime default getdate(),

Valore varchar (8000));

GO

-- creo la store procedure di inserimento record

create procedure fpsp_InsertBigRecord (@NumRecord int, @Testo char(1))

as

declare @Counter int

set @Counter = 1

while @Counter <= @NumRecord Begin

insert into dbo.BigInsert (Valore) values (replicate(@Testo,8000));

set @Counter = @Counter + 1;

end

GO

-- creo la Store procedures (per comodita) che presenta i dati sul log

create procedure fpsp_ShowLogDimension (@InstanceName varchar(50))

as

select Instance_Name, Counter_name, cntr_value

from sys.dm_os_performance_counters

where instance_name= 'TestRecoverySimple'

and cntr_type = 65792

and Counter_Name like '%Log%'

;

GO

-- leggo i valori iniziali del log

exec fpsp_ShowLogDimension 'TestRecoverySimple';

-- 1016 Kb (40% utilizzato), 0 Shrinks, 0 Growths, 1 Truncation

--- effettuo degli insert

exec fpsp_InsertBigRecord 2000, 'A';

--Leggo le dimensioni del log

exec fpsp_ShowLogDimension 'TestRecoverySimple';

-- NON e' aumentato: 1016 Kb (53% utilizzato), ma ha subito 75 Truncations

 

-- Inserimenti sotto transazione

begin tran;

exec fpsp_InsertBigRecord 100, 'B';

-- Rileggo le dimensioni del log

exec fpsp_ShowLogDimension 'TestRecoverySimple';

-- E' aumentato: 2040 Kb (73% utilizzato), 1 Growths e 2 truncation rispetto a prima (ora il valore e' 77)

commit;

exec fpsp_ShowLogDimension 'TestRecoverySimple';

-- L'autoshrink e' disabilitato per cui Non scende la dimensione (2040 Kb)

-- altri inserimenti senza transazioni attive

exec fpsp_InsertBigRecord 2000, 'C';

-- valuto di nuovo il log

exec fpsp_ShowLogDimension 'TestRecoverySimple';

-- Nessun inserimento da committare: Non ha avuto bisogno di aumentare (2040 Kb)

-- e' solo aumentato il numero di truncation effettuate (ora 96)

 

-- effettuo uno shrink

DBCC SHRINKDATABASE (TestRecoverySimple);

-- valuto di nuovo il log

exec fpsp_ShowLogDimension 'TestRecoverySimple';

-- le dimensioni sono scese:1016 Kb (36% utilizzato)

-- nuovi inserimenti sotto transazione

begin tran;

exec fpsp_InsertBigRecord 200, 'D';

-- valuto di nuovo il log

exec fpsp_ShowLogDimension 'TestRecoverySimple';

-- ha subito due grow (il valore ora e' 3) le dimensioni sono: 3064 Kb (83% usato) - log truncation = 123

commit;

exec fpsp_ShowLogDimension 'TestRecoverySimple';

-- 3064 kb (72%)

--effettuo lo shrink

DBCC SHRINKDATABASE (TestRecoverySimple);

exec fpsp_ShowLogDimension 'TestRecoverySimple';

-- ritorno alle dimensioni minime iniziali 1016 kb (35% occupato)

 

-- effettuo un select into

select * into dbo.NewBigTable from dbo.BigInsert;

exec fpsp_ShowLogDimension 'TestRecoverySimple';

-- Log size 2040 Kb (61% usato) l'attivita' di insert ha richiesto piu' spazio per il log

-- nuovo select into

select * into dbo.NewBigTable2 from dbo.BigInsert;

exec fpsp_ShowLogDimension 'TestRecoverySimple';

-- Non e' aumentato l'operazione era uguale a prima e non ha richiesto altro spazio

-- Log size 2040 Kb (57% usato)

 

-- nuovo select into

select * into dbo.NewBigTable3 from dbo.BigInsert;

exec fpsp_ShowLogDimension 'TestRecoverySimple';

-- Continua a non aumentare 2040 Kb (61% usato)

 

-- ora select into sotto transazione

begin tran

-- 1° select into

select * into dbo.NewBigTable4 from dbo.BigInsert;

exec fpsp_ShowLogDimension 'TestRecoverySimple';

-- non aumenta

---2° select into

select * into dbo.NewBigTable5 from dbo.BigInsert;

exec fpsp_ShowLogDimension 'TestRecoverySimple';

-- siamo sotto transazione la richiesta di spazio aumenta 3064 Kb (78% usate)

---3° select into

select * into dbo.NewBigTable6 from dbo.BigInsert;

exec fpsp_ShowLogDimension 'TestRecoverySimple';

-- siamo sotto transazione la richiesta di spazio aumenta ancora 4088 Kb (83% usate)

---4° select into

select * into dbo.NewBigTable7 from dbo.BigInsert;

exec fpsp_ShowLogDimension 'TestRecoverySimple';

-- siamo sotto transazione la richiesta di spazio aumenta ancora 5112 Kb (83% usate)

-- annullo

Rollback

exec fpsp_ShowLogDimension 'TestRecoverySimple';