Domanda

Ho una scommessa con il mio vecchio capo. Scommetto che SQL Server, quando alloca una nuova estensione, si alloca sempre dal pool di buffer e non controlla mai se c'è un posto sul disco in cui l'allocazione potrebbe essere archiviata. In sostanza, contesta che SQL Server dovrebbe verificare lo spazio disponibile sul LUN prima di assegnare una pagina. Questo sembra sbagliato, dal momento che potrei mettere il mio deposito sulla luna, il che causerebbe una grave latenza. Sento che vuole davvero che SQL Server porti sempre in una pagina dal disco in primo luogo e quindi esegui le attività DML.

Ecco la mia "prova" che ha torto. Se non sei d'accordo con la mia "prova", allora rispondi sicuramente con una migliore!

Creiamo un database e una tabella banali. Il modello di recupero del database verrà impostato su Simple e Auto_Create_Statistics verrà interrotto, al fine di ridurre al minimo il bloat del record di registro.

Prima di iniziare, lasciami divulgare la versione di SQL Server che sto usando.

SELECT @@VERSION;
-------------------------------------------------------------------------------------
Microsoft SQL Server 2012 - 11.0.2100.60 (X64) 
Developer Edition (64-bit) on Windows NT 6.1  (Build 7601: Service Pack 1)

Ora, il codice ...

USE master;
GO

IF DATABASEPROPERTYEX(N'PageAllocDemo' , N'Version') > 0 
      BEGIN
            ALTER DATABASE PageAllocDemo SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
            DROP DATABASE PageAllocDemo;
      END;
GO

CREATE DATABASE PageAllocDemo
GO

USE PageAllocDemo;
GO
SET NOCOUNT ON;
GO

-- Set the database to SIMPLE and turn off log generating crapola
ALTER DATABASE PageAllocDemo SET RECOVERY SIMPLE;
GO
ALTER DATABASE PageAllocDemo SET AUTO_CREATE_STATISTICS OFF;
GO

CREATE TABLE dbo.X
(
      c1 INT IDENTITY (1,1)
) ON [PRIMARY];
GO

Ora, controlliamo quante pagine sono state assegnate? Sospetto zero, poiché abbiamo creato solo una "tabella logica", nel nostro caso un mucchio vuoto.

-- How many pages are allocated to our table?
DBCC IND (PageAllocDemo,X,-1);
GO

Ora, cancella il registro.

-- Clear the log
CHECKPOINT;
GO

Cosa c'è attualmente nel registro?

-- What is in the log right now?
SELECT * FROM fn_dblog(NULL,NULL);
GO

/*

---------------------------------------
-- Operation -------------- Context ---
---------------------------------------
LOP_BEGIN_CKPT      LCX_NULL
LOP_XACT_CKPT       LCX_BOOT_PAGE_CKPT
LOP_END_CKPT        LCX_NULL

*/

Questo è previsto, poiché siamo nel semplice modello di recupero. Ora creeremo una transazione esplicita che inserirà un solo record nella nostra tabella; ma, prima di farlo, apriremo il monitoraggio del processo e filtrano per il nostro file MDF e LDF, nonché il PID per il processo SQL Server.

enter image description here

Inizia la transazione:

BEGIN TRAN

    INSERT INTO dbo.X DEFAULT VALUES;
    GO

Il monitor di processo mostra due scritture nel file di registro delle transazioni.enter image description here

Controlliamo i record di registro.

-- What is in the log right now?
    SELECT * FROM fn_dblog(NULL,NULL);

    /*
    I omitted all the log records for PFS, GAM, SGAM, etc.
    ---------------------------------------------------------------
    -- Operation -------------- Context ------- Transaction ID  ---
    ---------------------------------------------------------------
    LOP_BEGIN_XACT      LCX_NULL                0000:0000030e
    LOP_BEGIN_XACT      LCX_NULL                0000:0000030f
    LOP_FORMAT_PAGE     LCX_HEAP                0000:0000030f
    LOP_COMMIT_XACT     LCX_NULL                0000:0000030f
    LOP_INSERT_ROWS     LCX_HEAP                0000:0000030e
    LOP_COMMIT_XACT     LCX_NULL                0000:0000030e

*/

Ometto le allocazioni di bit map e PFS e possiamo vedere che una pagina è allocata e una riga viene inserita come si aspetterebbe.

Quante pagine sono assegnate al nostro heap?

-- How many pages are allocated to our table?
    DBCC IND (PageAllocDemo,X,-1);
    GO

    /*

    One IAM page and one data page and nothing else
    ---------------------------------
    PageFID PagePID     IAMFID IAMPID      
    ------- ----------- ------ ------ 
    1       264         NULL   NULL        
    1       231         1      264         

    */

Questo è come previsto. Abbiamo una pagina IAM e una pagina di dati. Ora, la nostra penultima azione sta commettendo la transazione. Mi aspetto che a questo punto si verifichi un flush di blocco di tronchi da 512b.

COMMIT TRAN;

enter image description here

Finiamo la "prova" con un'operazione di checkpoint. Finora, nulla è stato impegnato nel file di dati solo nel file di registro.

CHECKPOINT;
GO

enter image description here

Cool, le pagine di dati sono state arrossate sul disco come previsto.

La mia conclusione, dalle prove del monitor di processo è che SQL Server alloca in memoria, aggiunge il record in memoria e commette la pagina al disco tutto senza controllare nulla a livello di archiviazione.

Qualcuno si oppone a questa ipotesi? Se sì, perché?

Nessuna soluzione corretta

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a dba.stackexchange
scroll top