Le journal SQL Server enregistre-t-il les opérations non validées?

12

Je vois souvent des déclarations comme le journal du serveur sql enregistre chaque transaction et opération.

Mais je suis confus au sujet de ce qui se passe lorsqu'une transaction est finalement roulé en arrière .

Dites une transaction explicite a 3 déclarations: statement A, statement B, statement C, et enfin rollback statement D.

Maintenant, dites que lorsque l'exécution n'a pas atteint le rollback statement D, les modifications résultant de l' statements A through Cenregistrement seront-elles enregistrées dans le journal du serveur SQL?

Comprendre 1 :

Les déclarations A à D sont toutes enregistrées. SQL Server enregistre tout, quoi qu'il arrive.

Comprendre 2 : les modifications ne sont stockées que quelque part en mémoire et enregistrées uniquement pour se connecter lorsque SQL Server voit une commitinstruction. S'il s'avère qu'il s'agit d'une rollbackinstruction, SQL Server ignore simplement la transaction, aucune écriture dans le journal ne se produit car elle ne sert à rien. En d'autres termes, SQL Server enregistre lorsqu'il existe un résultat net avant et après les transactions.

Les deux semblent logiques, du moins pour moi, mais ils ne peuvent pas tous les deux avoir raison. Merci pour toute aide.

John Smith
la source
Bonjour, essayez [ systoolsgroup.com/sql-log-analyzer.html] (SQL Log Analyzer) pour analyser ce qui se passe dans le fichier journal. Vous pouvez essayer la version gratuite de SysTools SQL Log Analyzer pour ne prévisualiser que les données de journal SQL. J'espère que cela fonctionne pour toi.
Rylan08

Réponses:

13

Comprendre 1 est correct. SQL Server enregistre chaque opération qui modifie les données dans le journal des transactions. Une restauration est une modification des données, elle enregistre également cela dans le journal des transactions. En tant qu'exécution de l'instruction A, il écrit des données dans le journal des transactions et réserve également des données dans le journal des transactions au cas où l'instruction A doit être annulée. Il en va de même pour B et C. Lorsque vous annulez la transaction, plus d'informations seront écrites dans le journal.

Il existe de nombreuses façons de voir cela en action, voici donc une démo rapide. Voici la requête que je vais utiliser pour voir ce qui a été écrit dans le journal:

SELECT 
  COUNT(*) transaction_count
, SUM(database_transaction_log_bytes_used) used_bytes
, SUM(database_transaction_log_bytes_reserved) reserved_bytes
FROM sys.dm_tran_database_transactions
where database_id = 10;

Ma table:

create table TLOGDEMO (FLUFF VARCHAR(1000));

BEGIN TRANSACTION

La requête A utilise une journalisation minimale:

INSERT INTO TLOGDEMO WITH (TABLOCK)
SELECT REPLICATE('A', 1000)
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;

Après un:

╔═══════════════════╦════════════╦════════════════╗
 transaction_count  used_bytes  reserved_bytes 
╠═══════════════════╬════════════╬════════════════╣
                 1    24006640       175429451 
╚═══════════════════╩════════════╩════════════════╝

La requête B n'utilise pas de journalisation minimale:

INSERT INTO TLOGDEMO
SELECT REPLICATE('B', 1000)
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;

Après B:

╔═══════════════════╦════════════╦════════════════╗
 transaction_count  used_bytes  reserved_bytes 
╠═══════════════════╬════════════╬════════════════╣
                 1  7352935708      1613986255 
╚═══════════════════╩════════════╩════════════════╝

La requête C modifie moins de données:

INSERT INTO TLOGDEMO
SELECT REPLICATE('C', 1000)
FROM master..spt_values c;

Après C:

╔═══════════════════╦════════════╦════════════════╗
 transaction_count  used_bytes  reserved_bytes 
╠═══════════════════╬════════════╬════════════════╣
                 1  7355821748      1614545331 
╚═══════════════════╩════════════╩════════════════╝

Maintenant, je vais émettre un ROLLBACKet interroger le DMV pendant la restauration. Voici un tableau de quelques instantanés:

╔═══════════════════╦════════════╦════════════════╗
 transaction_count  used_bytes  reserved_bytes 
╠═══════════════════╬════════════╬════════════════╣
 1                  7393305528  1573797677     
 1                  7458767420  1502635737     
 1                  7682482356  1259440979     
 1                  7803881368  1127471233     
 ...                ...         ...            
╚═══════════════════╩════════════╩════════════════╝

Pendant le ROLLBACK, les octets utilisés augmentent et le nombre d'octets réservés diminue. C'est parce que SQL Server utilise l'espace qu'il a mis de côté avant pour annuler la transaction. Pour annuler la transaction, il doit modifier les données afin d'écrire plus de données dans le journal.

Joe Obbish
la source
8

Les modifications apportées aux tables de la base de données sont d'abord écrites dans le fichier journal, puis dans les tables elles-mêmes, d'abord en mémoire, puis, avec un processus asynchrone appelé CHECKPOINT, sur le disque. Ce mécanisme est connu sous le nom de WAL (Write-Ahead Logging) et est commun à toutes les bases de données relationnelles.

Le journal lui-même est d'abord écrit en mémoire (dans le tampon du journal, précisément) puis sur le disque, mais rien n'est touché sur les tables de la base de données tant que le journal n'a pas été écrit sur le disque.

Ce mécanisme permet à la fois de reporter les transactions validées et de revenir sur les transactions non validées pendant le processus de récupération. En ce qui concerne votre exemple, si quelque chose de mauvais s'est produit après statement Cet que vous avez eu un commitau lieu d'un rollback(vous ne pouvez pas le savoir à l'avance), sans enregistrer chaque étape de la transaction, le SGBDR n'aurait aucun moyen de récupérer la base de données de manière cohérente. et la transaction ne respecterait pas la D(durabilité) en ACID.

Lorsque certaines opérations sont annulées, c'est le fichier de données qui reçoit les modifications nettes (via CHECKPOINT), pas le fichier journal.

spaghettidba
la source
5

Comprendre 1 est correct, et spaghettidba et Joe ont de bonnes explications.

Si vous êtes intéressé par des tests par vous-même (sur une instance de test s'il vous plaît), vous pouvez utiliser le script ci-dessous:

--create a database and table for testing
USE master
GO
CREATE DATABASE tranlogtest
GO
USE tranlogtest
GO
CREATE TABLE t1
(junk char(1))

CHECKPOINT
GO

BEGIN TRAN
INSERT t1 VALUES ('a')
INSERT t1 VALUES ('b')
INSERT t1 VALUES ('c')

ROLLBACK
INSERT t1 VALUES ('d')

SELECT *
FROM fn_dblog(NULL,NULL)

Vous verrez que SQL Server enregistre tout, même les étapes effectuées pour annuler les opérations.

Forrest
la source