Чи записує журнал SQL Server невмілі операції?


12

Я часто бачу такі заяви, як журнал sql сервера, записує кожен перехід і операцію.

Але я плутати про те, що відбувається , коли транзакція в кінці кінців прокату назад .

Скажімо явна транзакція має 3 положення: statement A, statement B, statement C, і , нарешті rollback statement D.

Тепер скажіть, коли виконання не досягне rollback statement D, чи зміни, отримані в результаті statements A through Cзаписуються в журнал сервера sql?

Розуміння 1 :

Виписки від A до D все записуються. SQL Server записує все, незалежно від того.

Розуміння 2 : Модифікації зберігаються лише десь у пам'яті та записуються до журналу лише тоді, коли SQL Server бачить commitоператор. Якщо це виявляється rollbackзаявою, SQL Server просто ігнорує трансакріон, а записування в журнал не відбувається, тому що це не відповідає меті. Іншими словами, SQL Server реєструється, коли є чистий результат до та після транзакцій.

І те, і інше, здається логічним, але вони не можуть бути праві. Дякуємо за будь-яку допомогу.


Привіт, Спробуйте [ systoolsgroup.com/sql-log-analyzer.html] (SQL Log Analyzer) проаналізувати, що відбувається у файлі журналу. Ви можете спробувати безкоштовну версію SysTools SQL Log Analyzer лише для попереднього перегляду даних журналу SQL. Сподіваюся, це працює для вас.
Rylan08

Відповіді:


13

Розуміння 1 правильне. SQL Server записує кожну операцію, яка змінює дані в журнал транзакцій. Відкат - це зміна даних, тому він також записує їх до журналу транзакцій. Як оператор A run, він записує дані в журнал транзакцій, а також резервує дані в журналі транзакцій у випадку, якщо оператор A потрібно повернути назад. Те саме стосується B і C. При відкаті транзакції в журнал буде записано більше інформації.

Існує маса способів побачити це в дії, тому нижче наводиться швидка демонстрація. Ось запит, який я використаю, щоб побачити, що було записано в журнал:

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;

Мій стіл:

create table TLOGDEMO (FLUFF VARCHAR(1000));

BEGIN TRANSACTION

Запит A використовує мінімальний журнал:

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

Після A:

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

Запит B не використовує мінімальний журнал:

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

Після B:

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

Запит C змінює менше даних:

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

Після C:

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

Тепер я видам ROLLBACKі запитую DMV, поки відбудеться відкат. Нижче наведена таблиця з декількох знімків:

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

Під час ROLLBACKвикористання використовуваних байтів збільшується, а зарезервована кількість байтів зменшується. Це тому, що SQL Server використовує простір, відведений йому раніше для скасування транзакції. Для скасування транзакції він повинен змінити дані, щоб він записував більше даних у журнал.


8

Зміни таблиць баз даних записуються спочатку в файл журналу, потім у самі таблиці, спочатку в пам'ять, а потім, з асинхронним процесом, викликаним CHECKPOINT, на диск. Цей механізм відомий як WAL (Write-Ahead Logging) і загальний для всіх реляційних баз даних.

Сам журнал записується спочатку в пам'ять (точно в буфер журналу), а потім на диск, але нічого не торкається таблиць бази даних, поки журнал не буде записаний на диск.

Цей механізм дозволяє як прокручувати вперед здійснені транзакції, так і скасовувати невдалі транзакції в процесі відновлення. Що стосується вашого прикладу, якби щось трапилося після цього, statement Cа у вас був commitзамість цього rollback(ви не можете цього знати заздалегідь), не зберігаючи кожен крок транзакції, RDBMS не зможе відновити базу даних послідовно Таким чином, транзакція не відповідала б D(довговічність) в Росії ACID.

Коли деякі операції повертаються назад, файл даних отримує чисті зміни (через CHECKPOINT), а не файл журналу.


5

Розуміння 1 правильне, і спагеттідба та Джо мають хороші пояснення.

Якщо ви зацікавлені в тестуванні для себе (у тестовому екземплярі, будь ласка), ви можете скористатися наведеним нижче сценарієм:

--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)

Ви побачите, що SQL Server записує все, навіть кроки, зроблені для скасування операцій.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.