Tworzenie harmonogramów zadań SQL Server w Task Scheduler

SQLServerSchedule_WithoutAgent_000

SQL Server Agent jest powszechnie używany jako narzędzie służące do tworzenia tzw. jobów czyli określonych zadań do wykonania w zadanym harmonogramie. Co jednak gdy nie mam do dyspozycji SQL Server Agent lub z różnych przyczyn nie możemy go użyć (np. SQL Server Express w ogóle go nie zawiera)? W swojej karierze spotkałem kilka implementacji używających zewnętrznych ( w stosunku do SQL Server) narzędzi jak chociażby Control – M.  System operacyjny Windows oferuje nam jednak coś standardowego bez konieczności doinstalowywania zewnętrznych komponentów. W ramach niniejszego artykułu postaram się przedstawić sposób w jaki można wykonywać kopie zapasowe oraz inne skrypty związane z SQL Server wykorzystując TaskScheduler. Artykuł został zainspirowany przez jednego z czytelników naszego bloga (pozdrawiam Piotr), który potrzebował takiego rozwiązania, które będzie mogło wykonać kopie zapasowe w sposób systematyczny na wersji Express serwera SQL.

Na samym wstępie stwórzmy sobie skrypt w TSQL, który będzie robił kopie zapasowe. Na dysku systemowym C stworzyłem folder backups do którego nasze kopie zapasowe będą trafiać (pomińmy aspekt bezpieczeństwa i dobrych praktyk – w takim rozwiązaniu powinniśmy mieć wydzielone, bezpieczne miejsce na kopie i z całą pewnością nie powinien to być dysk systemowy). Skrypt, który będzie wykonywał pełną kopię bazy danych przedstawia się następująco:

Jest to standardowa składnia kopii zapasowych – jedyne o czym warto pamiętać to kompresja, którą jeśli mamy możliwość to włączmy. Oczywistym jest fakt, że taki skrypt można dowolnie rozbudować jednakże na nasze potrzeby demonstracyjne w pełni on wystarczy. Aby łatwiej nam było coś takiego wywołać wrzuciliśmy powyższy skrypt w procedurę składowaną, która będzie znajdowała się w bazie systemowej master (warto do trzymania skryptów utrzymaniowych, które będą działały na wielu bazach stworzyć sobie osobną bazę danych np. o nazwie Maintenance, w której to będziemy trzymać wszystkie obiekty tego typu).

Jak już mamy naszą procedurę to wywołajmy ją aby sprawdzić czy wszystko przebiegło zgodnie z planem:

Na poniższym zrzucie ekranowym możecie zauważyć, że obyło się bez problemów i nasza kopia zapasowa została wykonana poprawnie:

Przechodząc dalej musimy przyjrzeć się teraz narzędziu, które będzie spełniało rolę SQL Server Agent. Tak jak już wspomniałem wcześniej narzędziem tym będzie wbudowany w Windows Task Scheduler – wystarczy go wyszukać w menu start. To co jest charakterystyczne dla tego narzędzia to fakt, że bez problemu radzi on sobie z poleceniami linii komend. Standardową linią komend dla SQL Server jest sqlcmd, którego użyjemy w niniejszym przykładzie (nic nie stoi na przeszkodzie aby użyć dającego o wiele większe możliwości Powershell).

Linia komend rządzi się swoimi prawami dlatego aby nie wpisywać “na twardo’ całej komendy tworzącej kopie zapasową w polecenie sqlcmd stworzyliśmy procedurę, która znacznie uprości nam całe działanie. Wywołanie tejże procedury z sqlcmd wygląda następująco

Przełącznik -S wskazuje nazwę serwera bazodanowego do którego się łączymy (w naszym przypadku serwer bazodanowy znajduje się na tym samym serwerze co narzędzie które będziemy używać do wykonywania kopii zapasowych dlatego też wpisałem adres localhost), -E wskazuje, że będziemy używać tzw. Trusted Connection, a -Q to nic innego jak wskazanie zapytania , którego chcemy użyć. Oczywiście uwierzytelnienie w tym przypadku będzie wykonywane po koncie domenowym. Jeśli nie chcemy użyć tego sposobu możemy zawsze “przesiąść się” na uwierzytelnienie SQL Server. Na ten moment polegajmy jednak na uwierzytelnieniu Windows co w zdecydowanej większości przypadków będzie preferowaną opcją m.in ze względu na bezpieczeństwo.

Po wykonaniu tego zapytania powinniśmy otrzymać zwrot identyczny jak w przypadku wywołania z poziomu Management Studio:

Mamy już nasz skrypt – zapiszmy go zatem w pliku tekstowym w wybranej lokalizacji z rozszerzeniem np. bat lub cmd (rozszerzenie nie ma znaczenia ale warto stosować jedną konwencję nazewniczą dla wszystkich skryptów):

Jeśli chodzi o skrypt to mamy już wszystko gotowe, przejdźmy zatem do Task Schedulera aby utworzyć odpowiedni harmonogram. Po otworzeniu narzędzia naszym oczom powinien ukazać się widok podobny do poniższego:

Aby stworzyć nowe zadani wybieramy Action -> Create Task. W pierwszym oknie konfiguracyjnym będziemy mieli do ustawienia kilka opcji:

Oczywiście nadajemy nazwę naszemu zadaniu i ustawiamy opis. Następnie musimy ustawiamy użytkownika, który będzie określone zadanie uruchamiał. Jeżeli uruchamiamy zadanie sqlcmd, które z kolei używa uwierzytelnienia Windows wybieramy użytkownika, który będzie miał prawa aby nasza kopię zapasową wykonać – trzeba również pamiętać aby użytkownik ten miał prawa zapisu w folderze który wybraliśmy jako miejsce docelowe naszych kopii zapasowych. W moim przypadku będzie to Administartor (znów pomińmy kwestie bezpieczeństwa:) ).

W kolejnym kroku musimy wybrać czy zadanie ma zostać uruchomione tylko wtedy gdy użytkownik jest zalogowany czy w jakimkolwiek momencie – myślę, że w większości przypadków będziemy chcieli wykonywać zadanie bez względu na to czy jesteśmy zalogowani czy też nie i taką opcję wybrałem. Dodatkowo mamy opcję “do not store password”, która powinna być zaznaczona wtedy gdy odwołujemy się do lokalnych zasobów komputera (jeżeli odwołujemy się do zasobów spoza lokalnej maszyny warto pamiętać o tym, że przechowywanie hasła gdziekolwiek indziej niż kontroler domeny może być niezgodne z polityką bezpieczeństwa w naszej organizacji).

Kolejna zakładka o nazwie “Triggers” pozwala nam ustalić co będzie wyzwalaczem naszego zadania. W naszym przypadku będzie to nic innego jak harmonogram – wybieramy zatem “On a schedule” i musimy zdecydować jak często nasze zadanie będzie wykonywane. Jak możecie zauważyć poniżej wybrałem wykonywanie zadania codziennie o godzinie 3:42:

Podobnie jak w przypadku SQL Server Agent tak i tutaj możemy bardzo mocno dostosować harmonogram do naszych potrzeb. Nie będziemy omawiać każdej możliwej opcji – myślę, że jest to na tyle intuicyjne, że każdy sobie z tym poradzi. Trzeba pamiętać jedynie aby na samym końcu zaznaczyć “Enabled” aby od razu uaktywnić harmonogram.

Kolejną interesującą nas zakładką jest Actions – to właśnie w tym miejscu wskażemy utworzony wcześniej przez nas plik ze skryptem. Klikamy New i naszym oczom powinno pojawić się okno podobne do poniższego:

Tutaj nie mam już za wiele do zrobienia wystarczy wskazać plik bat/cmd który wcześniej utworzyliśmy. Kolejne zakładki pozwalają na dostosowanie naszego zadania. Conditions jak sama nazwa wskazuje pozwala określić warunki kiedy zadanie zostanie uruchomione:

Każda z powyższych opcji powinna być jasna – ciekawym rozwiązaniem jest tutaj uzależnienie wystartowania joba w zależności od tego czy połączenie sieciowe jest dostępne czy też nie. Jest to bardzo istotne szczególnie jeśli nasze pliki kopii mają zostać zapisane w lokalizacji sieciowej itp.

Zakładka settings jest niezmiernie istotna i powinniśmy zawsze dostosować ją do potrzeb konkretnego zadania:

W tym miejscu pamiętajmy o tym aby ostatnią opcję ustawić “Do not start a new instance” czyli w momencie gdy task jest już uruchomiony to aby task scheduler nie uruchomił nowego – unikamy dzięki temu efektu “nakładania się” zadań. Ponadto w moim przypadku zawsze zaznaczam opcję podobną do “Allow task to be run on demand” – pozwala ona na to aby uruchomić całe zadanie poza harmonogramem na żądanie – myślę, że warto mieć taką możliwość.  Warto również ustawić Timeout czyli “Stop the task if it runs longer than” tak aby w przypadku awarii lub innej niezidentyfikowanej przyczyny nasze działania nie trwały dłużej niż podany limit.  W moim odczuciu każde zadanie powinno mieć stosowny (rozsądny) limit czasowy z uwzględnieniem ryzyka jakie niesie ze sobą Rollback czyli wycofanie operacji, które może być kosztowniejsze niż kontynuacja działania. Często ustawianą w tym miejscu opcją jest również logika ponownego uruchamiania – na powyższym zrzucie ekranowym możecie zauważyć, że jeśli zadanie się nie powiedzie to będzie uruchamiane jeszcze trzykrotnie co 5 minut. Myślę, że warto coś takiego zaimplementować aby w przypadku chwilowej niedostępności bazy (bez wnikania w tym miejscu w przyczyny) spróbować raz jeszcze. Po zatwierdzeniu okna nasze zadanie zostanie dodane do narzędzia i będzie działało według zadanego harmonogramu.

Po utworzeniu zadania warto go przetestować (możemy to zrobić poza harmonogramem jeśli zaznaczyliśmy wspomnianą wcześniej opcję “Allow task to be run on demand”). Klikamy prawym przyciskiem myszy i z menu kontekstowego wybieramy Run:

Jeśli wszystko przebiegło pomyślnie powinniśmy w oknie głównym task schedulera zobaczyć odpowiednią informację:

Mając do dyspozycji takie narzędzie jak Task Scheduler w połączeniu z sqlcmd czy powershell mamy niemal nieograniczone możliwości harmonogramowania. Dzięki takiemu połączeniu możemy zbudować plany kopii zapasowych czy też zadania wykonujące aktualizacje statystyk, przebudowę/reorganizację indeksów czy chociażby sprawdzenie konsystencji bazy danych z wykorzystaniem DBCC CheckDB. Tak jak mogliście zauważyć można funkcjonować bez SQL Server Agent – w wielu przypadkach Task Scheduler daje nam o wiele większe możliwości, a jego konfiguracja jest bardzo prosta.Samo narzędzie nie jest również idealne i posiada liczne wady jak chociażby trudność zarządzania takimi zadaniami w porównaniu do prostoty oferowanej przez SQL Server Agent i pewne problemy z bezpieczeństwem jednakże nie ma rozwiązań idealnych, a Task Scheduler może rozwiązywać naprawdę wiele problemów. Mam nadzieję, że niniejszy post okazał się dla Was użyteczny i nie będziecie myśleć, że jesteście skazani na dyktaturę Agenta 🙂

Adrian Chodkowski
Follow me

Adrian Chodkowski

SQL geek, Data enthusiast, Consultant & Developer
Adrian Chodkowski
Follow me

Latest posts by Adrian Chodkowski (see all)

Leave a Comment

Your email address will not be published. Required fields are marked *