Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Използване на транзакция ROLLBACK в SQL Server

Въведение

Съвсем наскоро един мой колега дойде при мен в отчаяние, признавайки, че е издал изявление за актуализиране без клауза WHERE в таблица с ключово приложение. Последствията за предния край биха били ужасни, така че той се обърна директно към мен, защото спешно се нуждаеше от помощ за обръщане на ситуацията по какъвто и да е начин, преди имейлите и ескалацията да започнат да се изсипват.

Когато разгледахме ситуацията, установихме, че промените не са приложени във вторичната база данни. В повечето случаи изоставането между нашите първични и вторични бази данни е двадесет минути (имаме малко зашеметяващи, за да избегнем проблеми с производителността). Тъй като моят колега помоли за помощ веднага след осъзнаването на грешката, успяхме да възстановим данните от вторичната база данни. Описах стойността на такова забавяне в тази статия .

Преглед на сценария

Сценарият, който описах по-горе, не е необичаен. Една от причините това да се случва на обикновените потребители на SQL Server е, че SQL Server използва това, което се нарича неявни транзакции. Неявните транзакции са изключени по подразбиране, което означава, че SQL Server не очаква да издадете оператор COMMIT TRANSACTION в края на всеки израз. На практика всяко изявление се записва автоматично. Това е удобно и помага да се избегнат ситуации, в които сесиите, които тепърва ще бъдат ангажирани, в крайна сметка блокират ресурси и оказват влияние върху производителността. Брент Озар дава повече подробности за последиците за ефективността на IMPLICIT TRANSACTIONS =ON.

Въпреки това, малък недостатък на тази конфигурация (НЕМНИТЕЛНИ ТРАНЗАКЦИИ =ИЗКЛЮЧЕНО) е, че потребителите нямат възможност да преосмислят изявление и да издадат ROLLBACK, което е много често срещано в Oracle. Фиг. 1 показва опциите за ANSI заявка, налични в SQL Server Management Studio.

Фиг. 1 ANSI по подразбиране в SQL Server Management Studio

Използване на неявни транзакции

По същество проблемът, пред който сме изправени в тази конфигурация по подразбиране или най-желания ни клиентски инструмент, е, че не можем да ВРЪЩАНЕ, след като изпълним SQL израз. Можем да заобиколим това, като активираме ИМПЛИКТИВНИ ТРАНЗАКЦИИ в нашата сесия. Това ще ни даде възможност да ОТМЕНЯМ транзакции, ако трябва. Фиг. 2 и Фиг. 4 ни показват, че можем да включим тази настройка само за една сесия, въпреки че това не премахва риска потребителската сесия да блокира други, ако не бъдат издадени ROLLBACK или COMMIT.

Фиг. 2 НЯВЯВАЩИ ТРАНЗАКЦИИ В една сесия

-- Listing 1: UPDATE Table TAB2 with IMPLICIT_TRANSACTIONS ON
SET IMPLICIT_TRANSACTIONS ON

DECLARE @IMPLICIT_TRANSACTIONS VARCHAR(3) = 'OFF';  
IF ( (2 & @@OPTIONS) = 2 ) SET @IMPLICIT_TRANSACTIONS = 'ON';  
SELECT @IMPLICIT_TRANSACTIONS AS IMPLICIT_TRANSACTIONS;

USE KTrain
GO
SELECT * FROM Tab2;
GO

UPDATE TAB2
SET countryCode='SA'
-- WHERE fname='Joyce';
GO
SELECT * FROM Tab2;
GO

Фиг. 3 Всички редове са актуализирани

За да илюстрираме заобикалянето, описано тук, нека разгледаме SQL кода в листинг 1. Да предположим, че на обикновен потребител на SQL Server, млад разработчик, е даден набор от скриптове за изпълнение при определени условия . В скрипта клаузата WHERE е коментирана, защото се очаква всеки път, когато изпълняват този скрипт, те трябва да променят предиката. Разбира се, това е прост случай на употреба и рискът може да бъде адресиран по различни начини, но ние просто искаме да покажем възможността за извършване на връщане назад.

Припомнете си, че вече сме включили IMPLICIT TRANSACTION, така че когато изпълним тази инструкция, SQL Server ще очаква от нас или да ЗАДЪЛЖИМ, или да ОТМЕНИМ транзакцията. Намерението на разработчика е да актуализира countryCode на Джойс Афам към „SA“, тъй като е имигрирала в Южна Африка. Фиг. 3 ни показва, че разработчикът, докато се опитва да направи това, случайно е актуализирал всички редове със стойността SA като countryCode . Те забелязват това и издават връщане назад.

Фиг. 4 Издаване на ROLLBACK

Фиг. 5 НЯВЯВАЩИ ТРАНЗАКЦИИ В Друга сесия

В другата сесия обаче, в която не сме включили НЯВНИ ТРАНЗАКЦИИ, откриваме, че разработчикът не може да се възстанови от грешката си. В този случай те не могат успешно да издадат ROLLBACK. След това възстановяването ще доведе до възстановяване на данни.

Фиг. 6 ОТМЕНЯНЕТО не е възможно, ако НЕ ВКЛЮЧЕТЕ НЯКВАНИ ТРАНЗАКЦИИ

Използване на явни транзакции

Друг подход за постигане на същия ефект е затварянето на DML в транзакция чрез изрично посочване BEGIN TRAN. Отново е много важно да завършите транзакцията - като използвате COMMIT или ROLLBACK. В контекста на тази дискусия ние издаваме ОТМЕНЯНЕ, тъй като осъзнаваме, че има грешка в кода.

-- Listing 2: UPDATE Table TAB2 with Explicit Transaction

BEGIN TRAN 
GO
USE KTrain
GO
SELECT * FROM Tab2;
GO

UPDATE TAB2
SET countryCode='GH'
-- WHERE fname='Joyce';
GO
SELECT * FROM Tab2;
GO

ROLLBACK;

SELECT * FROM Tab2;
GO

- Listing 3: Corrected UPDATE Statement

BEGIN TRAN 
GO
USE KTrain
GO
SELECT * FROM Tab2;
GO

UPDATE TAB2
SET countryCode='SA'
WHERE fname='Joyce';
GO
SELECT * FROM Tab2;
GO

Заключение

В тази статия засегнахме накратко едно добро решение за създаване на възможности за ROLLBACK и по този начин смекчаване на грешките на потребителите, произтичащи от грешен DML. Ние също така подчертахме ключов риск от този подход, който е неволно блокиране. DBA може да започне разследване на възможното присъствие на този риск, като подаде заявка за sys.dm_tran_session_transactions, sys.dm_tran_locks и подобни обекти за динамично управление.

Препратки

  1. Коригиране на загуба на данни чрез изпращане на регистрационни файлове с отложено възстановяване

  2. Задаване на неявни транзакции

  3. Задайте неявните транзакции като лоша идея

  4. DMV за транзакции


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Различно представяне на UUID в Java Hibernate и SQL Server

  2. Как да получа последно въведен идентификатор?

  3. Как да увеличите допустимия размер на прикачените файлове при изпращане на имейл в SQL Server (T-SQL)

  4. Как да получите дата във формат ГГГГ-ММ-ДД от TSQL поле за дата и час?

  5. SQL Server:използвайте параметър в CREATE DATABASE