ROLLBACK est-il une opération rapide?

Réponses:

14

Pour SQL Server, vous pourriez faire valoir qu'une opération de validation n'est rien d'autre que l'écriture de LOP_COMMIT_XACT dans le fichier journal et la libération des verrous, ce qui va bien sûr être plus rapide que le ROLLBACK de chaque action effectuée par votre transaction depuis BEGIN TRAN.

Si vous envisagez chaque action d'une transaction, pas seulement la validation, je dirais toujours que votre déclaration n'est pas vraie. En excluant les facteurs externes, la vitesse du disque de journal par rapport à la vitesse du disque de données par exemple, il est probable que la restauration de tout travail effectué par une transaction soit plus rapide que d'effectuer le travail en premier lieu.

Une restauration consiste à lire un fichier séquentiel de modifications et à les appliquer aux pages de données en mémoire. Le «travail» d'origine devait générer un plan d'exécution, acquérir des pages, joindre des lignes, etc.

Edit: Le ça dépend un peu ...

@JackDouglas a signalé cet article qui décrit l'une des situations où la restauration peut prendre beaucoup plus de temps que l'opération d'origine. L'exemple étant une transaction de 14 heures, qui utilise inévitablement le parallélisme, il faut plus de 48 heures pour revenir en arrière, car la restauration est principalement à filetage unique. Vous seriez très probablement également en train de baratter le pool de tampons à plusieurs reprises, donc vous n'inversez plus les modifications apportées aux pages en mémoire.

Donc, une version révisée de ma réponse précédente. Le recul est-il beaucoup plus lent? Tout bien considéré, pour une transaction OLTP typique, ce n'est pas le cas. En dehors des limites du typique, cela peut prendre plus de temps pour "défaire" que "faire" mais (est-ce un tordement de langue potentiel?) Pourquoi dépendra de la façon dont le "faire" a été fait.

Edit2: Suite à la discussion dans les commentaires, voici un très artificiel exemple pour démontrer que le travail en cours est le facteur majeur pour déterminer les dépenses relatives de validation vs restauration en tant qu'opérations.

Créez deux tableaux et emballez-les de manière inefficace (espace perdu par page):

SET STATISTICS IO OFF;
SET STATISTICS TIME OFF;
SET NOCOUNT ON;
GO

CREATE TABLE dbo.Foo
(
    col1 INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
    , col2 CHAR(4000) NOT NULL DEFAULT REPLICATE('A', 4000)
)

CREATE TABLE dbo.Bar
(
    col1 INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
    , col2 CHAR(4000) NOT NULL DEFAULT REPLICATE('A', 4000)
)
GO

INSERT dbo.Foo DEFAULT VALUES
GO 100000

INSERT dbo.Bar DEFAULT VALUES
GO 100000

Exécutez une "mauvaise" requête de mise à jour, en mesurant le temps nécessaire pour effectuer le travail et le temps nécessaire pour émettre la validation.

DECLARE 
    @StartTime DATETIME2
    , @Rows INT

SET @Rows = 1

CHECKPOINT
DBCC DROPCLEANBUFFERS

BEGIN TRANSACTION

SET @StartTime = SYSDATETIME()

UPDATE
    dbo.bar
SET
    col2 = REPLICATE('B', 4000)
FROM
    dbo.bar b
INNER JOIN
    (
    SELECT TOP(@Rows)
        col1
    FROM
        dbo.foo
    ORDER BY
        NEWID()
    ) f
ON  f.col1 = b.col1
OPTION (MAXDOP 1)

SELECT 'Find and update row', DATEDIFF(ms, @StartTime, SYSDATETIME())

SET @StartTime = SYSDATETIME()

COMMIT TRANSACTION

SELECT 'Commit', DATEDIFF(ms, @StartTime, SYSDATETIME())
GO

Faites de même, mais émettez et mesurez la restauration.

    DECLARE 
    @StartTime DATETIME2
    , @Rows INT

SET @Rows = 1

CHECKPOINT
DBCC DROPCLEANBUFFERS

BEGIN TRANSACTION

SET @StartTime = SYSDATETIME()

UPDATE
    dbo.bar
SET
    col2 = REPLICATE('B', 4000)
FROM
    dbo.bar b
INNER JOIN
    (
    SELECT TOP(@Rows)
        col1
    FROM
        dbo.foo
    ORDER BY
        NEWID()
    ) f
ON  f.col1 = b.col1
OPTION (MAXDOP 1)

SELECT 'Find and update row', DATEDIFF(ms, @StartTime, SYSDATETIME())

SET @StartTime = SYSDATETIME()

ROLLBACK TRANSACTION

SELECT 'Rollback', DATEDIFF(ms, @StartTime, SYSDATETIME())
GO

Avec @ Rows = 1, j'obtiens un résultat raisonnablement cohérent:

  • 5500 ms pour la recherche / mise à jour
  • 3 ms commit
  • 1 ms de recul

Avec @ Rows = 100:

  • 8500 ms trouver / mettre à jour
  • 15 ms commit
  • Retour en arrière de 15 ms

Avec @ Rows = 1000:

  • 15000 ms trouver / mettre à jour
  • 10ms commit
  • 500 ms de recul

Retour à la question d'origine. Si vous mesurez le temps nécessaire pour effectuer le travail plus la validation, la restauration est gagnante car la majorité de ce travail est consacrée à la recherche de la ligne à mettre à jour, et non à la modification des données. Si vous examinez l'opération de validation de manière isolée, il doit être clair que la validation ne fonctionne que très peu en tant que telle. L'engagement est "J'ai fini".

Mark Storey-Smith
la source
2
«moins de travail» n'est pas nécessairement «plus rapide»
Jack Douglas
Je savais que cela begin tranaugmente simplement le compteur de transactions. Si je vous ai bien compris, rdbms fait toutes les tâches (jointures de lignes, génération de plans d'exécution ...) chez COMMIT?
garik
3
Non, tout le travail est effectué avant la validation. L'opération de validation elle-même fait relativement peu.
Mark Storey-Smith
@Mark J'ai fait des tests grossiers et prêts en insérant des lignes de 2 m et en validant ou en annulant. La durée globale, y compris la restauration, variait de 10 à 30 secondes, contre 6 à 14 secondes pour la durée totale, y compris la validation. YMMV bien sûr, mais cela indique que la restauration approximative est presque aussi longue ou plus longue que la transaction d'origine au moins dans mon environnement.
Jack Douglas
2
Si vous deviez mesurer le temps nécessaire pour terminer l'opération de validation, je m'attendrais à ce qu'il soit minime, à moins qu'un point de contrôle ne soit émis en même temps (ce qui est distinct et indépendant). C'est mon point de vue, le commit fait très peu alors que le rollback fait tout ce qui s'est passé avant le commit plus un peu plus. La variance de vos tests suggère d'autres facteurs en jeu, mais je vais certainement essayer de rassembler certains scripts plus tard.
Mark Storey-Smith
13

Pour Oracle, la restauration peut prendre plusieurs fois plus de temps que le temps nécessaire pour effectuer les modifications qui sont annulées. Cela n'a souvent pas d'importance car

  1. Aucun verrou n'est maintenu pendant que la transaction est annulée
  2. Il est géré par un processus d'arrière-plan de faible priorité

Pour SQL Server, je ne sais pas si la situation est la même, mais quelqu'un d'autre dira si ce n'est pas le cas ...

Quant au "pourquoi", je dirais que le rollbackdevrait être rare , généralement seulement si quelque chose a mal tourné, et bien sûr commitest probablement beaucoup plus courant - il est donc logique d'optimiser pourcommit

Jack Douglas
la source
9

La restauration n'est pas seulement «oh, peu importe» - dans de nombreux cas, elle doit vraiment annuler ce qu'elle avait déjà fait. Il n'y a aucune règle selon laquelle l'opération de restauration sera toujours plus lente ou toujours plus rapide que l'opération d'origine, bien que même si la transaction d'origine s'est déroulée en parallèle, la restauration est monothread. Si vous attendez, je suggère qu'il est plus sûr de continuer à attendre.

Tout cela change avec SQL Server 2019, bien sûr, et la récupération de base de données accélérée (qui, à une pénalité également variable, permet une restauration instantanée quelle que soit la taille des données).

Aaron Bertrand
la source
2
Et nous avons tous eu cette conversation "ça prend du temps à revenir en arrière, redémarrons-le" à un moment donné, n'est-ce pas?
Mark Storey-Smith
J'ai vu de nombreux clients le faire. Certains s'en sortent relativement indemnes, d'autres ont beaucoup moins de chance.
Aaron Bertrand
1
@ MarkStorey-Smith - Si vous redémarrez en cours de restauration, SQL Server ne doit-il pas continuer sa restauration au démarrage?
Nick Chammas
2
@Nick cela dépend - si la restauration a été bloquée avant le redémarrage, par exemple, elle peut se comporter beaucoup plus rapidement après un redémarrage du service car cet autre processus vient d'être tué. Il y a BEAUCOUP de "et si" dans ce scénario - chaque fois que vous redémarrez un serveur ou redémarrez un service pour "résoudre" un problème, il y a probablement des problèmes beaucoup plus graves en jeu.
Aaron Bertrand
2
@ Nick, oui c'est exactement ce qui se passe. Mon commentaire était destiné à être "ironique", en ce sens que vous finissez inévitablement par l'expliquer au déclencheur, des gens heureux qui veulent redémarrer chaque fois que quelque chose ne se comporte pas comme prévu.
Mark Storey-Smith,
8

Toutes les transactions ne verront pas leur activité de validation bien meilleure que leur annulation. Un tel cas est l'opération de suppression dans SQL. Lorsqu'une transaction supprime des lignes, ces lignes sont marquées comme enregistrements fantômes. Une fois qu'un commit est émis et qu'une tâche de nettoyage des enregistrements fantômes démarre, seuls ces enregistrements sont «supprimés».

Si une restauration a été émise à la place, elle supprime simplement les marques fantômes de ces enregistrements, et non les instructions d'insertion intensives.

StanleyJohns
la source
Bon exemple de la façon dont certaines opérations sont optimisées pour la restauration.
Mark Storey-Smith
5

Pas tous. PostgreSQL ne prend pas plus de temps pour revenir en arrière que pour valider car les deux opérations sont effectivement identiques en termes d'E / S disque. Je ne pense pas que ce soit une question d'être optimisé pour la validation autant que de savoir pour quelles autres requêtes on optimise.

La question fondamentale est de savoir comment vous abordez la disposition sur le disque et comment cela affecte la validation par rapport à la restauration. Les bases de données principales qui annulent plus lentement que la validation ont tendance à déplacer les données, en particulier des tables en cluster, hors des structures de données principales et à les placer dans un segment d'annulation lors de la mise à jour des données. Cela signifie que pour vous engager, supprimez simplement le segment d'annulation, mais pour annuler, vous devez recopier toutes les données.

Pour PostgreSQL, toutes les tables sont des tables de tas et les index sont séparés. Cela signifie que lors de la restauration ou de la validation, aucune donnée ne doit être réorganisée. Cela rend la validation et la restauration rapides.

Cependant, cela ralentit certaines autres choses. Une recherche de clé primaire, par exemple, doit traverser un fichier d'index puis frapper la table de tas (en supposant qu'aucun index de couverture ne soit applicable). Ce n'est pas énorme, mais cela ajoute une recherche de page supplémentaire ou peut-être même quelques recherches de page aléatoires (si de nombreuses mises à jour se sont produites sur cette ligne) pour vérifier d'autres informations et visibilité.

La vitesse ici n'est cependant pas une question d'optimisation dans PostgreSQL pour les opérations d'écriture par rapport à celles de lecture. C'est une réticence à privilégier certaines opérations de lecture au-dessus d'autres. Par conséquent, PostgreSQL fonctionne en moyenne à peu près aussi bien que les autres bases de données. Ce ne sont que certaines opérations qui peuvent être plus rapides ou plus lentes.

Je pense donc que la réponse réelle est que les bases de données sont optimisées pour certaines charges de travail du côté lecture, ce qui entraîne des défis du côté écriture. Généralement, en cas de question, les validations sont généralement, mais pas toujours, privilégiées par rapport aux annulations. Cela dépend cependant des implications de l'une ou l'autre (les mises à jour sont différentes des suppressions).

Chris Travers
la source
Bonne réponse, mais une petite critique: "Pour PostgreSQL, toutes les tables sont des tables de tas et les index sont séparés. Cela signifie que lors de la restauration ou de la validation, aucune donnée ne doit être réorganisée" ce n'est pas la raison pour laquelle aucune donnée ne doit être réarrangé, c'est plutôt parce que "les bases de données majeures qui reculent plus lentement que la validation ont tendance à déplacer les données", et pas pg, comme vous l'avez mentionné. Oracle utilise également par défaut le stockage en tas: la principale différence est qu'Oracle utilise "annuler" et récupère tout l'espace lors de la validation / restauration plutôt que de suivre la route "vide".
Jack Douglas