Pełny backup bazy i przyrostowy

Dla baz zwykle w maintance plan trzeba przygotować backup, gdzie np. w weekend/codziennie następuje pełen backup bazy, a w między czasie w krótszych interwałach dziennych/godzinowych następuje backupowanie przyrostowe. 

1) Pełny backup z kompresją:

BACKUP DATABASE [test1]
TO  DISK = N'C:\Baza_MDF\test1_20250815_1601_full.bak' 
WITH 
NOFORMAT, 
NOINIT,  
NAME = N'test1-Full Database Backup', 
SKIP, 
NOREWIND, 
NOUNLOAD, 
COMPRESSION,
STATS = 10, 
CHECKSUM
GO

declare @backupSetId as int
select @backupSetId = position 
from msdb..backupset 
where database_name=N'test1' and
backup_set_id=(select max(backup_set_id) 
from msdb..backupset where database_name=N'test1' )

if @backupSetId is null 
begin raiserror(N'Verify failed. Backup information for database ''test1'' not found.', 16, 1) end
RESTORE VERIFYONLY FROM  DISK = N'C:\Baza_MDF\test1_20250815_1601_full.bak' 
WITH  
FILE = @backupSetId,  
NOUNLOAD,  
NOREWIND
GO

1) Przyrostowy backup z kompresją:

BACKUP DATABASE [test1] 
TO  DISK = N'C:\Baza_MDF\test1_20250815_1605_differential.bak' 
WITH  DIFFERENTIAL , 
NOFORMAT, 
NOINIT,  
NAME = N'test1-Diff Database Backup', 
SKIP, 
NOREWIND, 
NOUNLOAD, 
COMPRESSION,  
STATS = 10, 
CHECKSUM
GO

declare @backupSetId as int
select @backupSetId = position 
from msdb..backupset 
where database_name=N'test1' and
backup_set_id=(select max(backup_set_id) from msdb..backupset where database_name=N'test1' )

if @backupSetId is null 
begin raiserror(N'Verify failed. Backup information for database ''test1'' not found.', 16, 1) end
RESTORE VERIFYONLY FROM  DISK = N'C:\Baza_MDF\test1_20250815_1605_differential.bak' WITH  FILE = @backupSetId,  NOUNLOAD,  NOREWIND
GO

3) Przywracamy bazę z fulla i danego differential backup

Pamiętać: W SQL Server jak już przywrócisz bazę z FULL do jakiegoś Diff z opcją WITH RECOVERY, to baza wraca do normalnego trybu i łańcuch przywracania się kończy

Jeśli chcesz, aby kolejne backupy były kontynuacją tego stanu po Diff 1, 
to po przywróceniu z Diff 1 robisz od razu nowy full backup

a) Ubijamy sesje do danej bazy 

USE master;
GO

DECLARE @dbName SYSNAME = N'test1'; -- wpisz nazwę bazy
DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += 'KILL ' + CAST(s.session_id AS NVARCHAR(10)) + ';'
FROM sys.dm_exec_sessions AS s
JOIN sys.dm_exec_requests AS r
    ON s.session_id = r.session_id
WHERE r.database_id = DB_ID(@dbName)
  AND s.session_id <> @@SPID; -- pomijamy swoje połączenie

-- Dodatkowo uwzględniamy sesje idle z sys.dm_exec_sessions
SELECT @sql += 'KILL ' + CAST(s.session_id AS NVARCHAR(10)) + ';'
FROM sys.dm_exec_sessions AS s
WHERE s.database_id = DB_ID(@dbName)
  AND s.session_id <> @@SPID;

IF @sql <> ''
BEGIN
    PRINT @sql; -- możesz sprawdzić przed wykonaniem
    EXEC sp_executesql @sql;
END
ELSE
    PRINT 'Brak aktywnych połączeń do bazy ' + @dbName;

b) Restore do danego punktu

Mając full i dany differental możemy zrobić restore w oparciu o daną przyrostówkę:

use master
RESTORE DATABASE test1
FROM DISK = 'C:\Baza_MDF\test1_20250815_1637_full.bak'
WITH NORECOVERY, REPLACE;

use master
RESTORE DATABASE test1
FROM DISK = 'C:\Baza_MDF\test1_20250815_1639_differential.bak'
WITH RECOVERY;

 

Przeniesienie plików bazy MSSQL do nowej lokalizacji

Przeniesienie bazy mssql do nowej lokalizacji wymaga odpowiedniej kolejności:

1) Sprawdź aktualne ścieżki plików

use master
SELECT name, physical_name, type_desc
FROM sys.master_files
WHERE database_id = DB_ID('test1');

wynik z name i physical_name skopiuj sobie na bok, z tej lokalizacji będziesz kopiował zwrócone pliki do nowego folderu

2) Odłącz bazę (DETACH)

USE master;
GO
ALTER DATABASE test1 
SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
EXEC sp_detach_db 'test1';


3) Fizyczne przeniesienie plików

Skopiuj pliki bazy tj: .mdf, .ndf, .ldf w nowe lokalizacje na dysku.

4) Prawa do folderu i plików

a) Upewnij się, że konto usługi SQL Server ma dostęp do nowego katalogu (prawo odczytu/zapisu).
Zwykle: 
NT Service\MSSQLSERVER (ale sprawdzić kto uruchamia usługę)
Klikasz docelowy folder z bazą - właściwości - Zabezpieczenia - Edytuj - Dodaj

właściwości folderu
właściwości folderu dodanie użytkownika MSSQL

b) Jeśli wykonujesz podłączenie z MngStudio logując się swoim kontem domenowym,  upewnij się aby ten użytkownik również miał prawa folderu z plikami baz tj. opcja zaawansowane i dodać swoje konto.
Bez tych punktów MSSQL będzie miał błąd dostępu do plików i nie podepnie bazy.

5. Podłącz bazę z nowymi ścieżkami (ATTACH)

USE master;
GO
CREATE DATABASE test1 ON 
    (FILENAME = 'C:\Baza_MDF\test1.mdf'),
    (FILENAME = 'C:\Baza
_MDF\test1.ndf'),
    (FILENAME = 'F:\Baza
_MDF\test1.ldf')
FOR ATTACH;



Zmiana tempdb do nowej lokalizacji

Przeniesienie bazy tempdb do nowej lokalizacji:

1) Wykonujemy zapytanie, które przygotuje nam SQL do zmiany lokalizacji tempdb

DECLARE @new_path NVARCHAR(4000) = N'T:\New_File_Path\';
 
SELECT
      N'ALTER DATABASE tempdb MODIFY FILE (NAME = ' + QUOTENAME(f.[name]) + N', '
    + N'FILENAME = ''' + @new_path + RIGHT(physical_name, CHARINDEX('\', REVERSE(physical_name)) -1)
    + ''');'
    AS [AlterCommand]
FROM sys.master_files f
WHERE f.database_id = DB_ID(N'tempdb');

 Wynik:

ALTER DATABASE tempdb MODIFY FILE (NAME = [tempdev], FILENAME = 'T:\New_File_Path\tempdb.mdf');
ALTER DATABASE tempdb MODIFY FILE (NAME = [templog], FILENAME = 'T:\New_File_Path\templog.ldf');
ALTER DATABASE tempdb MODIFY FILE (NAME = [temp2], FILENAME = 'T:\New_File_Path\tempdb_mssql_2.ndf');
ALTER DATABASE tempdb MODIFY FILE (NAME = [temp3], FILENAME = 'T:\New_File_Path\tempdb_mssql_3.ndf');
ALTER DATABASE tempdb MODIFY FILE (NAME = [temp4], FILENAME = 'T:\New_File_Path\tempdb_mssql_4.ndf');
ALTER DATABASE tempdb MODIFY FILE (NAME = [temp5], FILENAME = 'T:\New_File_Path\tempdb_mssql_5.ndf');
ALTER DATABASE tempdb MODIFY FILE (NAME = [temp6], FILENAME = 'T:\New_File_Path\tempdb_mssql_6.ndf');
ALTER DATABASE tempdb MODIFY FILE (NAME = [temp7], FILENAME = 'T:\New_File_Path\tempdb_mssql_7.ndf');
ALTER DATABASE tempdb MODIFY FILE (NAME = [temp8], FILENAME = 'T:\New_File_Path\tempdb_mssql_8.ndf');


3) Tworzymy nowy folder ma dysku pod tempdb


4) Użytkownik, który uruchomia usługę MSSQL musi być dodany aby miał prawa (najlepiej pełne) do dysku. 
Zwykle jest to użytkownik domenowy, albo wbudowane wirtualne konto MSSQL np: NT Service\MSSQLSERVER

5) Restart MSSQL (bazy tempdb w tym momencie się odtwarzają na nowej lokalizacji)

Extended Events

Najważniejsze założenia XEvents'ów:
- zbieranie informacji (mniej lub więcej w zależności od potrzeb) niezbędnych do monitoringu, identyfikacji lub rozwiązywania problemów wydajności na serwerze (wg MS ma to zastępować Profilera)
- wysoce konfigurowalne, lekkie obciążenie i skalowalne
- dane logów zapisywane w sesjach zrzut do pliku, ew. w ring buffer

Aby zebrać dane należy przejść w MngStudio:
Management/Extended Events/Sessions i PPM wybrać New Sessions Wizard

Kroki kreatora sesji:
1. Introducions (wstęp co to jest za narzędzie)
2. Set Session Properties (wprowadź nazwę sesji i włącz czy ma się uruchamiać przy starcie serwera)
3. Choose Template (MS ma kilka wybudowanych szablonów w zależności od tego co mierzymy)
    a) Locks and Blocks
    b) Profiler Equivalents
    c) Query Executions
    d) System Monitoring
    e) User Templates
4) Select Events To Capture (tu wybieramy zdarzenia, które chcemy gromadzić, w związku z tym, że jest ich multum, w tym przykładzie biorę tylko zdarzenie login z kategorii session, kanał Analytic z paczki sqlserver. Zdarzenie to ma kilka wierszy danych stanowiących zbiór tego zdarzenia, jak na screenie)

XEvents - wybór zdarzeń jakie chcemy logować



5) Capture Global Fields (wybieramy dodatkowe pola (akcje) jakie chcemy gromadzić, będą to systemowe akcje, które możemy wrzucić na tzw. dokładkę, aby mieć powiązanie z naszymi wcześniejszymi danymi np. client_pid etc.)
6) Set Session Event Filters (ciekawa opcja, gdzie możemy zawęzić wybór danych, dot. danej bazy, danego użytkownika, tu w zależności od kolekcjonowania danych możemy robić na nich dowolne filtry)
7) Specify Ssession Data Storage (wrzut do loga i jak chcemy gromadzić dane, wszystko czy ostatnie logi)
8) Summary (podsumowanie wizarda)
9) Create Event Session (potwierdzenie wyboru i uruchomienie)

Czytanie logów

SELECT event_data = CONVERT(XML, event_data)
FROM sys.fn_xe_file_target_read_file(N'Y:\XEventsLogs\aaaa*.xel', NULL, NULL, NULL);

ew. klikając
Pod stworzoną sesją XEvents wybierając PPM View Target Data...



SQL Server na Linux 1GB RAM (obraz Docker)

Czy SQL Server na Linuxie na maszynie 1GB RAM ma sens? Jest wiele tanich VPS z 1GB i istnieje pokusa zabawy.

Próbując zainstalować jednak otrzymamy komunikat:
This program requires a machine with at least 2000 megabytes of memory.

Przetestowałem to rozwiązanie na Linuxie (RHEL, Ubuntu), Zapakowałem instancję w Docker ze specjalnym obrazem justin2004/mssql_server_tiny (to obraz SQL Server 2017 i jest skonfigurowany aby omijać konfigurację sprzętową, co pozwala go instalować na maszynie z mniej niż 2GB ram).

Poniżej prosta konfiguracja i kilka wyjaśnień:
-e 'MSSQL_PID=Express' (biorę Express mniejszy narzut na pamięć, a mając VPS np. publiczy nie łamiesz licencji MS)
-p 4444:1433 (mapuję standardowy port sqlserver 1433 na własny 4444)
-v /sqldata:/var/opt/mssql (mapuję domyślny katalog mssql w /var/opt/mssql na własny /sqldata i tam ustawiam domyślne katalogi na data,log,backup,dump)
--memory-swap -1 (jak zabraknie fizycznego ram, zrzucam pamięć na dysk do pełnego jego wykorzystania)
--name ms1 (to moja nazwa instancji w Docker)
--hostname ms1 (to moja nazwa instancji w SQLServer)
--d justin2004/mssql_server_tiny

Na terminalu w Linux jeśli masz już Docker wpisz polecenie na uruchomienie obrazu:

sudo docker run
-e 'ACCEPT_EULA=Y'
-e 'SA_PASSWORD=WpiszTwojeMocneHaslo'
-e 'MSSQL_PID=Express'
-e 'MSSQL_COLLATION=Polish_CI_AS'
-p 4444:1433
-v /sqldata:/var/opt/mssql
-e 'TZ=Europe/Warsaw'
-e 'MSSQL_DATA_DIR=/sqldata/data'
-e 'MSSQL_LOG_DIR=/sqldata/log'
-e 'MSSQL_BACKUP_DIR=/sqldata/backup'
-e 'MSSQL_DUMP_DIR=/sqldata/dump'
--memory-swap -1
--name ms1
--hostname ms1
-d justin2004/mssql_server_tiny

PS: Po uruchomieniu instancja owszem działa, jednak w miarę im dłużej chodzi i kilka prostych workloadów zaraz sprawi, że będziesz otrzymywał błędy związane z pamięcią. Moim zdaniem nie warto na dłuższą metę w to się bawić i szukać VPS gdzie postawimy SQL Server z 4GB minimum do prostych zastosowań.

 


Audyt na poziomie bazy danych i serwera

Mamy dwa poziomy audytu jaki możemy przeprowadzić w SQL Server, tj.
- na samej instancji, zbieranie info z serwera
- na bazie i zbieranie logów z konkretnej bazy danych

1. Audyt na bazie danych

1.1) Polega na stworzeniu konfiguracji Audytu, a następnie Specyfikacji Audytu per baza
1.2) Tworzymy Audyt. Rozwijamy drzewko instancji, wybieramy Security/Audits/New Audit...
1.3) Wpisujemy gdzie logować zebrane dane, u mnie do pliku 20GB nadpisujący się.

Tworzenie audytu
Tworzenie nowego audytu




















1.4) Tworzymy specyfikację audytu dla bazy.
1.5) Rozwijamy drzewo instancji, wybieramy konkretną bazę danych, dalej Security/Database Audit Specifications/New Database Audit Specification...
1.6) Wpisujemy co chcemy logować, tj.

- Audit Action Type (typ akcji), u mnie instrukcja SELECT
- Object Class (klasa obiektu), u mnie to będzie typ SCHEMA
- Object Name (nazwa obiektu), u mnie to będzie dbo ze SCHEMA
- Principal Name (główny powiązany), u mnie to będzie każdy kto leży do grupy public, a więc wszyscy

w polu Audit wybieramy nasz wcześniej stworzony obiekt Audit, i koniec. Audyt jeszcze nie działa włączamy go na poziomie obiektu Audit.

 
Specyfikacja audytu dla bazy
Specyfikacja audytu na bazę


 

 

 

 

 

 

 

 

 

2. Audyt na serwerze

Podobnie jak w pkt 1, tworzymy konfigurację Audytu, tj. gdzie będziemy logować, ja wykorzystam tu ten sam obiekt

2.1) Tworzymy specyfikację audytu dla serwera. Rozwijamy drzewo instancji i dalej Security/Audits/Server Audit Specification/New Server Audit Specification...

Wpisujemy co chcemy logować, tj.

- Audit Action Type (typ akcji), u mnie instrukcja SUCCESSFUL_LOGIN_GROUP (czyli kto się zalogował)
- Object Class (klasa obiektu), brak, tu typ akcji nie pozwala na wybranie obiektu
- Object Name (nazwa obiektu),  brak, tu typ akcji nie pozwala na wybranie obiektu
- Principal Name (główny powiązany),  brak, tu typ akcji nie pozwala na wybranie obiektu

w polu Audit wybieramy nasz wcześniej stworzony obiekt Audit, i koniec. Audyt jeszcze nie działa włączamy go na poziomie obiektu Audit. 

PS: Dokładne opisy wszystkich akcji jakie możemy logować są na MSDN

https://learn.microsoft.com/en-us/sql/relational-databases/security/auditing/sql-server-audit-action-groups-and-actions?view=sql-server-ver16

w tabelach per db: Database-level audit action groups
w tabeli per serwer: Server-level audit action groups

Specyfikacja audytu na serwer








 

 


3. Czytanie logów

Mając już logowanie, możemy czytać te logi bezpośrednio funkcją systemową sys.fn_get_audit_file, ew. zapakować to w widok na bazie master i czytać już globalnie i filtrować przez kolumnę database_name

SELECT *
FROM sys.fn_get_audit_file(
    'Y:\AuditLogs\*.sqlaudit',
    DEFAULT,
    DEFAULT
);
GO