Инструкция: MS SQL shrink/сжатие базы TempDB без перезапуска SQL Server

Как бы много нам не было известно — мы всё равно всегда готовы изучать всё новое. В этой статье я покажу вам как выполнить сжатие временной базы данных TempDB без остановки работающего экземпляра MS SQL Server и при этом не зная ни количества файлов, ни их имена в БД TempDB.

Давайте разберемся что же это? И зачем так необходимо?

При работе 1С:Предприятия в клиент-серверном варианте интенсивно используются временные таблицы. Эти таблицы хранятся в системной базе данных TempDB. В процессе работы временная база данных может значительно увеличиваться в размерах и привести к заполнению всего диска.

 

Причиной увеличения размера базы данных TempDB, как правило, является невозможность автоматической очистки журнала транзакций и повторного использования свободного пространства из-за наличия активных транзакций, использующих объекты этой базы данных. Неограниченный рост может вызвать проблемы, связанные с сервером, вплоть до остановки MS SQL Server. В результате — недоступность баз. Что в свою очередь вызовет остановку в работе всех пользователей 1С использующих базы на этом сервере.

 

Так вот, чтобы не допустить ничего подобного и ужасного следует выполнить следующие основные действия по уменьшению размера базы данных TempDB до требуемой величины:

1. Перезапустить MS SQL Server. В этом случае размер базы данных TempDB будет установлен по умолчанию.

2. Сжать базу данных TempDB.

3. Уменьшить размер отдельных файлов.

4. Переместить базу данных TempDB на диск большего размера.

 

Решил я эту задачу путем уменьшения размера отдельных файлов.

 

Но для начала немного вводной информации. Временная база данных является системной базой данных, которая используется как для системных, так и для прикладных задач. Вот часть из них:

 

  • Выполнение запросов с инструкциями ORDER BY, GROUP BY или операторами множеств (UNION, INTERSECT, EXCEPT).
  • Создание временных таблиц и табличных переменных (например в 1С часто используют #t, #t1 и т.п.).
  • Создание и обновление индексов.
  • Использование табличных функций.
  • Использование триггеров.
  • Использование больших объектов (varchar(max), nvarchar(max), varbinary(max), text, ntext, image, xml) как параметров или переменных.
  • Выполнение скриптов с использованием курсоров типа static или keyset.
  • Уровень изоляции транзакций с версионностью (SNAPSHOT).
  • Выполнение команды DBCC CHECK.
  • Использование Database mail.

Также TempDB хранит много временной (кешированной) информации, которая используется для ускорения запросов.

 

Если место в TempDB уже освободилось, то для освобождения места на диске можно выполнить ее сжатие (shrink). Сделать это можно в SSMS студии:

 

Инструкция: MS SQL shrink/сжатие базы TempDB без перезапуска SQL Server - 42CLOUDS

 

либо запросом:

 

Инструкция: MS SQL shrink/сжатие базы TempDB без перезапуска SQL Server - 42CLOUDS

Здесь вы можете убедиться, что сжатие tempdb не похоже на сжатие любой другой базы данных. Вероятней всего операция shrink не привела к уменьшению файла БД, значит необходимо очистить различные кэш сервера и повторить shrink.

 

Важно. Все перечисленные ниже операции удаляют все виды кеш, что влияет на производительность сервера, пока они не будут восстановлены SQL Server. Помимо этого все будет удалено из буферов и записано на диск. Это доп. нагрузка на подсистему ввода/вывода. После этого можно сжать файлы, что влияет на производительность чтения/записи. И наконец, все процессы, которые запрашивают данные, должны будут извлечь данные из подсистемы ввода/вывода в буферы. Это значительно влияет на производительность системы в целом. Не выполняйте операции без крайней необходимости!

 

Вначале хотелось бы напомнить про самый простой способ. Если не используется производственная среда (например, среда разработки), то лучше всего перезапустить службу SQL Server. Это вернет tempdb к его размеру по умолчанию. Но если нет возможности перезапуска службы? В таком случае необходимо сжать TempDB без остановки MS SQL. Для этого используются следующие команды T-SQL:

 

Команда Описание Инструкция для SSMS
DBCC DROPCLEANBUFFERS Создаем checkpoint, чтобы сбросить на диск кешированные индексы и буферы страницы данных CHECKPOINT;
GO
DBCC DROPCLEANBUFFERS;
GO
DBCC FREEPROCCACHE Чистим кеш хранимых процедур. Это означает, что некоторые запросы и хранимые процедуры придется перекомпилировать при следующем их запуске. Хотя компиляция происходит автоматически, можно заметить значительное снижение производительности в первые несколько запусков запросов и процедур DBCC FREEPROCCACHE;
GO
DBCC FREESYSTEMCACHE Эта операция аналогична FREEPROCCACHE, за исключением того, что она влияет на другие типы кеш. DBCC FREESYSTEMCACHE (‘ALL’);
GO
DBCC FREESESSIONCACHE Чистим кеш сессий. Это связано с распределенными запросами (запросами между серверами) DBCC FREESESSIONCACHE;
GO
DBCC SHRINKFILE Это тот же инструмент, который используется для сжатия любого файла базы данных в TempDB или других базах данных. Это шаг, который фактически освобождает нераспределенное пространство из файла базы данных. Этот шаг самый “хитрый”. Во время процесса сжатия никакое другое действие не должно использовать базу данных tempdb (например бекапирование). Т.е. не должно быть открытых транзакций. Открытые транзакции могут привести к сбою операции DBCC DBCC SHRINKFILE (TEMPDEV, 1024);
Новый размер файла в МБ
GO

На практике TempDB состоит из нескольких файлов. На различных серверах их название и кол-во отличаются см. Рис1 и Рис2.

 

Рисунок 1

Рисунок 1

 

Рисунок 2

Рисунок 2

 

Как же выполнить DBCC SHRINKFILE заранее, не зная кол-ва файлов и их имена в TempDB?

 

Проще всего обратится не к имени файла, а к его порядковому номеру в базе. Это демонстрирует листинг кода скрипта. Скрипт формирует текст T-SQL для выполнения из командной строки, в результате выполнения которого получаются команды вида:

 

USE [tempdb]
CHECKPOINT
DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS
DBCC FREEPROCCACHE WITH NO_INFOMSGS
DBCC FREESYSTEMCACHE ('ALL') WITH NO_INFOMSGS
DBCC FREESESSIONCACHE WITH NO_INFOMSGS
DBCC SHRINKDATABASE ([tempdb]) WITH NO_INFOMSGS
DBCC SHRINKFILE (1,64) WITH NO_INFOMSGS
DBCC SHRINKFILE (2,64) WITH NO_INFOMSGS
DBCC SHRINKFILE (3,64) WITH NO_INFOMSGS
DBCC SHRINKFILE (4,64) WITH NO_INFOMSGS
DBCC SHRINKFILE (5,64) WITH NO_INFOMSGS
DBCC SHRINKFILE (6,64) WITH NO_INFOMSGS
DBCC SHRINKFILE (7,64) WITH NO_INFOMSGS
DBCC SHRINKFILE (8,64) WITH NO_INFOMSGS
DBCC SHRINKFILE (9,64) WITH NO_INFOMSGS

 

Обратите внимание, что в тексте нет инструкции GO. GO не является ключевым словом T-SQL, это инструкция SQL Server Management Studio, позволяющая разделять отдельные конструкции в скрипте. Параметр WITH NO_INFOMSGS просто подавляет все информационные сообщения.

 

Листинг скрипта:

/* сжатие tempdb */
SET NOCOUNT ON;
SET XACT_ABORT ON;
SET ARITHABORT ON;
SET QUOTED_IDENTIFIER ON;

DECLARE @cmd VARCHAR(1000), @dbid int, @file_id int, @name nvarchar(128), @dbname sysname, @sizeTempDB int;

SET @dbname='tempdb'
SET @sizeTempDB = 64; --размер до которого будем сжимать


IF OBJECT_ID('tempdb..#tmpdbFile') IS NOT NULL
BEGIN
DROP TABLE #tmpdbFile
END

--создаем и заполняем таблицу с именами логических файлов
CREATE TABLE #tmpdbFile (id int IDENTITY(1,1), [dbid] int, [file_id] int, [name] sysname, [dbname] sysname, isdone bit);

INSERT INTO #tmpdbFile ([dbid], [file_id], [name], [dbname], [isdone])
SELECT s_mf.database_id, s_mf.[file_id], s_mf.[name], d.name, 0
FROM sys.databases d
Left JOIN sys.master_files s_mf ON d.database_id = s_mf.database_id
WHERE db_name(s_mf.database_id) = @dbname
--and (s_mf.size * 8.0 / 1024) >= @sizeTempDB
ORDER BY s_mf.[file_id];


SELECT @cmd=''
SELECT @cmd = @cmd + char(13) + char(10) + 'USE [' + @dbname + ']'
SELECT @cmd = @cmd + char(13) + char(10) + ''
--Создаем checkpoint, чтобы сбросить на диск кешированные индексы и буферы страницы данных
SELECT @cmd = @cmd + char(13) + char(10) + 'CHECKPOINT'
SELECT @cmd = @cmd + char(13) + char(10) + 'DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS'
--Чистим кеш хранимых процедур:
SELECT @cmd = @cmd + char(13) + char(10) + 'DBCC FREEPROCCACHE WITH NO_INFOMSGS'
--Очищаем остальные типы кешей:
SELECT @cmd = @cmd + char(13) + char(10) + 'DBCC FREESYSTEMCACHE (''ALL'') WITH NO_INFOMSGS'
--Чистим кеш сессий:
SELECT @cmd = @cmd + char(13) + char(10) + 'DBCC FREESESSIONCACHE WITH NO_INFOMSGS'
--Cжимаем базу tempdb:
SELECT @cmd = @cmd + char(13) + char(10) + 'DBCC SHRINKDATABASE ([' + @dbname + ']) WITH NO_INFOMSGS'

--Формируем команды на сжатие файлов
IF (SELECT COUNT(id) FROM #tmpdbFile) > 0
BEGIN
WHILE (SELECT COUNT(id) FROM #tmpdbFile WHERE isdone = 0) > 0
BEGIN
SELECT TOP 1 @dbname = [dbname], @dbid = [dbid], @file_id = [file_id], @name = [name] FROM #tmpdbFile WHERE isdone = 0

SELECT @cmd = @cmd + char(13) + char(10) + 'DBCC SHRINKFILE (' + CONVERT(varchar(2),@file_id) + ',' + cast(@sizeTempDB as nvarchar) +') WITH NO_INFOMSGS'

UPDATE #tmpdbFile
SET isdone = 1
WHERE [dbid] = @dbid AND name = @name

END
END;
--print (@cmd);
exec (@cmd);

IF OBJECT_ID('tempdb..#tmpdbFile') IS NOT NULL
BEGIN
DROP TABLE #tmpdbFile
END

GO

 

В большинстве случаев достаточно выполнить только DBCC FREEPROCCACHE, что позволит сжать базу данных TempDB (т.е. нет необходимости в выполнении DBCC DROPCLEANBUFFERS; DBCC FREESYSTEMCACHE (‘ALL’); DBCC FREESESSIONCACHE)

 

В результате выполнения скрипта мы получаем сжатый до возможного (но не меньше указанного нами) размера файлы базы TempDB:

 

До выполнения скрипта После выполнения скрипта
Инструкция: MS SQL shrink/сжатие базы TempDB без перезапуска SQL Server - 42CLOUDS
Инструкция: MS SQL shrink/сжатие базы TempDB без перезапуска SQL Server - 42CLOUDS

Дисковое пространство освободилось, MS SQL Server продолжает работать, у пользователей не было прерывания в работе. И это главное! Пользователи работают, а администратору есть над чем задуматься — почему же так вырос TempDB. Какие действия (осознанные или неосознанные) привели к росту базы? Надо разбираться. Но это совсем другая задача, решение которой требует более детальной проработки.

Ваш личный сервер 1С за 1 день

Забудьте о затратах на оборудование и лицензии. Наша инфраструктура обеспечит вам гарантию надежности и безопасности данных.

0 0 голоса
Рейтинг

14 комментариев
Ранние Сортировка
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
Владимир
Владимир
2 года назад

последний скрипт приведенный в статье не может быть выполнен из-за ошибки синтаксиса

42Clouds
42Clouds
2 года назад

Владимир, здравствуйте)
Вы правы. Спасибо, что написали комментарий. В ближайшее время отредактируем статью.

Daniel
Daniel
1 год назад

Спасибо за скрипт

42Clouds
42Clouds
1 год назад

Здравствуйте!
Спасибо, что выбираете нас, ваша обратная связь дает нам стимул работать еще лучше.

Евгений
Евгений
1 год назад

Спасибо за крипт. tempDb умудрилась съест терабайт. Надо было срочно подрезать потому как начали падать пользователи. Скрипт помог поправить ситуацию очень быстро. С замедлением пришлось мириться примерно пол часа. Рост был связан с двумя независящими процессами. Массовой перепроведение документов для базы вин учета и загрузкой звонков из внешней базы астерикса.

42Clouds
42Clouds
1 год назад

Здравствуйте!
Спасибо, что выбираете нас, ваша обратная связь дает нам стимул работать еще лучше.

Андрей
Андрей
1 год назад

Спасибо за скрипт, помог, 2 недели потратил на решение

42Clouds
42Clouds
1 год назад

Здравствуйте!
Спасибо, что выбираете нас, ваша обратная связь дает нам стимул работать еще лучше.

Владимир
Владимир
1 год назад

Огромное вам спасибо за скрипт!

42Clouds
42Clouds
1 год назад

Здравствуйте!
Спасибо, что выбираете нас, ваша обратная связь дает нам стимул работать еще лучше.

Светогоръ
Светогоръ
1 год назад

Добрый день. К сожалению, скрипт не помог. При этом нет активных длинных транзакций или запросов. Можете подсказать, куда еще можно смотреть в этом случае?

42Clouds
42Clouds
1 год назад

Здравствуйте!
Если скрипт не может сжать tempdb, это означает, что база данных активно используется. При этом дело не обязательно в длительных транзакциях — любая сортировка или группировка в запросе также требует ресурсов tempdb. В таком случае вы можете определить, что именно «занимает» место, используя следующий скрипт.
Этот скрипт выводит данные на текущий момент. Однако вы можете организовать сбор данных в течение определенного периода, например, суток. Это позволит вам увидеть, какие запросы наиболее активно используют tempdb в разное время, и уже детально разобраться с этими запросами.
https://dropmefiles.com/DnM7Z

Игорь
Игорь
4 месяца назад

можете выложить скрипт заново, каждый день стал расти tempdb ни с того ни с сего, хотелось бы найти причину. Заранее спасибо

42 Clouds
42 Clouds
4 месяца назад

Здравствуйте!

Скрипт можно скачать по ссылке https://dropmefiles.com/Z6GYl.

Оставьте заявку. Мы свяжемся с вами в самое ближайшее время.

*нажимая на кнопку, Вы даете согласие на обработку персональных данных

С наступающим Новым Годом!

У вас 0

Упс… Кажется, не хватает снежинок.
Лови больше снежинок на сайте.

Снеговик

1С в облаке
— это не страшно!

Инструкция: MS SQL shrink/сжатие базы TempDB без перезапуска SQL Server - 42CLOUDS

Нажимая на кнопку, Вы даете согласие на обработку персональных данных

Оставьте отзыв о нас

Расскажите, как сервис 42Clouds помог вашему бизнесу.

Отзыв будет опубликован после проверки модератором.

Оставьте заявку. Мы свяжемся с вами в самое ближайшее время.

*нажимая на кнопку, Вы даете согласие на обработку персональных данных