Adam Tkocz

Adam Tkocz Teraz już
właściciel, znaczy
katastrofa się
zbliża

Temat: backup za pomocą sqlcmd

MSSQL 2008R2 Express uruchomiony na WIN7/64. Na tym serwerze chodzi między innymi baza SQL programu Płatnik. W instrukcji administratora płatnika jest podany sposób na wykonanie backupu z linii poleceń:
sqlcmd -S WINSERVER\INSERTGT -U sa -P "" -Q "BACKUP DATABASE platnik TO DISK ='C:\PlikiUdostepnione\Ksiegowosc\NaszeDane\PlatnikBCKP%DATE%.dat' WITH NAME = 'platnik_backup', FORMAT"

Niestety, bez komunikatu o błędzie wracam do prompta.

Natomiast jeśli pominę parametry uwierzytelniania -U oraz -P, to backup się wykonuje. Na stronach MS wyczytałem, że w takim wypadku stosowana jest autentykacja Windows.

Nie wiem, czy mam się tym martwić? Docelowo ta linia poleceń ma być wykonywana cyklicznie (zaplanowane zadania), jako reakcja na sygnał z UPSa (usługa) na brak zasilania oraz czasem ręcznie.

Nie wiem, czy i jak walczyć z tym uwierzytelnianiem. Użytkownik "sa" ma na 99.9% puste hasło. Zmiana w powyższym poleceniu hasła na inne wywala błąd:

Msg 18456, Level 14, State 1, Server WINSERVER\INSERTGT, Line 1
Login failed for user 'sa'.
Jarosław Kędzierski

Jarosław Kędzierski Admin od okienek

Temat: backup za pomocą sqlcmd

Jeśli chodzi o uwierzytelnianie Windows...
Twoja kopia bazy danych wykonuje się ponieważ wykonujesz polecenie na administratora SQLServer (prawdopodobnie na prawach użytkownika, który zainstalował SQL Server). Gdy ustawisz cykliczne wykonywanie komendy musisz zadbać, by użytkownik, na prawach którego będzie wykonywana miał odpowiednie uprawnienia. Jeśli np. będziesz wykonywał logując się swoim kontem - nie
widzę problemu.

Jeśli chodzi o logowanie poprzez użytkownika z pustym hasłem. Próbowałem, faktycznie wogóle nawet nie próbuje nawiązywać połączenia... natomiast zaczęło mi działać, gdy wprowadziłem jakiekolwiek hasło :). Swoją drogą szlachetnie byłoby posiadać jakieś hasło na sa. A jeśli tego nie chcesz załóż innego użytkownika na prawach sysadmin z loginem i hasłem i pewnie będzie git :)

komenda SQL zakładająca użytkownika backup z hasłem backup,123:
CREATE LOGIN [backup] WITH PASSWORD=N'backup,123', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
GO
EXEC master..sp_addsrvrolemember @loginame = N'backup', @rolename = N'sysadmin'
GO

Pozdrawiam
JArekJarosław Kędzierski edytował(a) ten post dnia 07.11.11 o godzinie 18:52
Adam Tkocz

Adam Tkocz Teraz już
właściciel, znaczy
katastrofa się
zbliża

Temat: backup za pomocą sqlcmd

Uwierzytelnianie Win... testy backupu z linii poleceń rzeczywiście robię z użytkownika z dużymi uprawnieniami, którego używam do konfiguracji serwera. I to jest OK, jeśli chodzi o ręczny backup. Być może sprawa się nieco skomplikuje, gdy zacznę dodawać polecenia backupu do harmonogramu zadań i do akcji wykonywanej podczas przejścia serwera na zasilanie z UPS. Bo z powodu mojego kompletnego braku zrozumienia mechanizmów uwierzytelniania w win i sql i związków między nimi najłatwiej mi takie rzeczy robić z moimi credentials. Ale to nie jest chyba zbyt sensowne.

User "sa" - u mnie z pustym hasłem nic, z "jakimkolwiek" natomiast była próba logowania ale wyrzucało błąd, tak jak wcześniej pisałem.

Teraz ta komenda SQL - zadziałała. W SSMS pojawił się użytkownik, hasło mu wymieniłem na inne. Backup się wykonał. Czyli w zasadzie OK. Ale czy to jest takie mocniej szlachetne jeśli chodzi o bezpieczeństwo, skoro hasło jest podane jawnie w linii poleceń, którą będe używał? Zaczynam się zastanawiać, czy nie będzie faktycznie najsensowniej pozostać przy autentykacji Win i zadbać o to (a wcześniej się nauczyć), żeby uruchamiać backup z właściwymi uprawnieniami i nie martwić się SQLem.

Wtedy pozostanie tylko ustawienie hasła dla "sa" i przekonanie księgowych, że damy radę zmienić parametry logowania do bazy insertgt i płatnika.

Ech, przerasta mnie to. adam tkocz edytował(a) ten post dnia 07.11.11 o godzinie 20:35
Daniel N.

Daniel N. Senior IT Architect,
DBA

Temat: backup za pomocą sqlcmd

Stwórz sobie scheduled task, który będzie wykonywał twojego batcha z backupem, powinno Ci to w zupełności wystarczyć.
Do wykonania backupu nie musisz mieć loginu w roli sysadmin, wystarczy rola bazodanowa o nazwie db_backupoperator.

http://msdn.microsoft.com/en-us/library/ms189121.aspx
Jarosław Kędzierski

Jarosław Kędzierski Admin od okienek

Temat: backup za pomocą sqlcmd

Oczywiście Daniel masz rację - upraszczałem, częściowo celowo.

Tak się tłumaczę trochę, bo adminowałem SQLem i też sysadmin mnie drażnił :)

Adam, jeśli będziesz potrzebował instrukcji krok po kroku, da się załatwić :), ale wydaje mi się, że szybko sam załapiesz. MS-SQL prosty dosyć jest w administracji. Nawet ja się nauczyłem ;P
Adam Tkocz

Adam Tkocz Teraz już
właściciel, znaczy
katastrofa się
zbliża

Temat: backup za pomocą sqlcmd

Dzięki koledzy,

Instrukcja step by step by się oczywiście przydała. Ale tak po prawdzie to bardziej mi się przyda każdy kawałek wiedzy i zrozumienia działania tego, co sam sobie tu narobiłem, żeby w razie potrzeby umieć zmodyfikować/naprawić/odtworzyć mechanizmy.

Opcja Jarka, jak wcześniej pisałem zadziałała. Czyli na teraz mam 2 możliwości - albo używam credentialsów z Win, albo użytkownika backup z SQL.

Sensowna wydaje się też sugestia Daniela. Ale z godzinę mi zajęło znalezienie takiej roli (db_backupoperator). Bo nie dotyczy servera SQLa chyba tylko poszczególnych baz danych (a mam 3 teraz). Innymi słowy - musiałbym tworzyć 3 razy takiego samego usera, z takim samym hasłem i w przyszłości pamiętać, że w razie coś to 3 x trzeba modyfikować. Chyba, że coś źle zrozumiałem.

Na pewno do tematu wrócę, teraz pora zabrać się za praktyczne zastosowanie polecenia do backupu w formie jakichś sensownych .BATów.
Adam Tkocz

Adam Tkocz Teraz już
właściciel, znaczy
katastrofa się
zbliża

Temat: backup za pomocą sqlcmd

No to się pojawiło drobne zagadnienie. Mam już napisanego pierwszego BATa, który backupuje bazy. Cały backup trwa w tej chwili ok. 3min30 sek. W wyniku daje pliki łącznie ok 200MB. Sama wielkość pliku nie ma większego znaczenia, dyski są z gumy w końcu. Ale ten czas mnie niepokoi. O ile przy normalnych backupach to nie ma znaczenia to przy wyłączeniu prądu przypuszczam, że będę miał maks 10-15 minut do awaryjnego wyłączenia serwera przez UPS.

I pytanie - czy i jak mogę włączyć na etapie backupu jakąś kompresję, żeby eksperymentalnie sprawdzić, czy będzie szybciej? Normalne backupy to sobie jakimś zipem spakuję czy coś.

Edit: chyba widzę już, że darmowy MS SQL Express nie ma możliwości natywnie pakować plikówadam tkocz edytował(a) ten post dnia 08.11.11 o godzinie 19:12
Michał Dziubek

Michał Dziubek Programista,
INFORM\'1

Temat: backup za pomocą sqlcmd

Tak tylko dodam, że jeżeli przekazujesz zapytanie lub skrypt z pliku za pomocą sqlcmd, to warto dodać jeszcze parametr o, żeby widzieć czy sam backup wykonał się z poziomu bazy:
sqlcmd -S WINSERVER\INSERTGT -U sa -P "" -Q "BACKUP DATABASE platnik TO DISK ='C:\PlikiUdostepnione\Ksiegowosc\NaszeDane\PlatnikBCKP%DATE%.dat' WITH NAME = 'platnik_backup', FORMAT" -o C:\PlikiUdostepnione\Ksiegowosc\NaszeDane\backup.log


A tak uzupełniając to warto sie zainteresować:
http://www.sqldbatips.com/showarticle.asp?ID=27
Jarosław Kędzierski

Jarosław Kędzierski Admin od okienek

Temat: backup za pomocą sqlcmd

No tak, zresztą kompresja raczej spowolni niż przyspieszy....

Z drugiej strony... rozumiem, ze backup będzie robił się BARDZO CZĘSTO. Proponuję więc stworzyć plan kopii zapasowych, nie wszystkie tp musi być pełny backup.

W SQL Server można wykonywać:
- pełne kopie
- kopie przyrostowe
- kopie logu transakcyjnego.

Nie wiem jak często chcesz backupować bazę, ale wykonanie raz dziennie pełnej kopii, a następnie backupowanie tylko logu transakcyjnego na pewno warto przetestować.

aby potem odtworzyć taką kopię trzeba przywrócić ostatnią pełną kopię, a następnie wszystkie kopie logu - więc żaden plik nie może zostać pominięty (od ostatniej pełnej kopii).

Mam nadzieję, że ten trop trochę pomoże.
Pozdrawiam
JArek

P.S. Co do uprawnień...na bazach danych są użytkownicy, na serwerze loginy. Loginy wiążą się z użytkownikami, albo i nie wiążą wtedy są 'osieroceni'. Z tym tematem możesz się spotkać, gdybyś potrzebował odtworzyć swoje bazy na innym serwerze. Warto trochę zgłębić temat. Nadając prawa do poszczególnych baz tworzy się jeden login (z jednym hasłem), a następnie dodaje prawa do baz, tworząc tam użytkowników. Użytkownik może już istnieć, dla przykładu z tego powodu, że baza została odtworzona z backupu na serwerze, na którym był identyczny użytkownik. W takim przypadku najlepiej założyć sam login a użytkownika po prostu powiązać :) Polecam trochę poczytać na ten temat, bo jest dosyć "życiowy" :)
Szymon P.

Szymon P. Databricks, Azure
Data Factory, MS SQL
SERVER

Temat: backup za pomocą sqlcmd

adam tkocz:
Nie wiem, czy i jak walczyć z tym uwierzytelnianiem. Użytkownik "sa" ma na 99.9% puste hasło. Zmiana w powyższym poleceniu hasła na inne wywala błąd:

Ja może odbiegnę trochę od tematu ale w best practices mocno zalecają disablowanie użytkownika sa, zmianę hasła sa i nawet ZMIANĘ NAZWY loginu. Przyjdzie kotś kto zechce to w taki sposób pozmieniać i później wam się wykrzaczy. Użytkownika 'sa' się w ogóle w normalnych warunkach nie powinno używać (on jest tylko dla 'backward compatibility') a micro$oft zaleca, gdzie tylko się da korzystać z autentykacji windows, więc jak masz możliwośc to działajcie na autentykacji windowsSzymon P. edytował(a) ten post dnia 08.11.11 o godzinie 21:34
Adam Tkocz

Adam Tkocz Teraz już
właściciel, znaczy
katastrofa się
zbliża

Temat: backup za pomocą sqlcmd

Strasznie dużo sugestii pojawiło. Postaram się w skrócie odpowiedzieć.
1) Uwaga Michała dot. logu z backupu - bez dyskusji wdrożę. Oryginalny archiwizator inserta właśnie "logował" w pliku tekstowym czynności

2) Jarek - kopie chcę robić raz dziennie i zachowywać je wg może nieco dziwnego schematu: trzymam kopie dzienne z każdego dnia ostatniego tygodnia, ze 4 czy 5 kopii "tygodniowych" z ostatnich kilku niedziel np oraz kopie "miesięczne" na zawsze.
Przy "zastanych" objętościach plików i czasach backupu nie będę się wbijał na razie w żadne przyrostowe kopie, żeby sobie głowy nie turbować kolejnym zagadnieniem i nieco bardziej skomplikowanym odtwarzaniem w razie coś. Co to jest log transakcyjny
nawet nie wiem :)

Kompresja... Hmmm, znalazłem coś takiego:
http://sourceforge.net/projects/mssqlcompressed/
Nie wiem, jak mi się udało to odpalić (o tym później) ale się udało. Poniżej zawartość testowego BATA:
 msbp.exe backup "db(database=XYZ ;instancename=INSERTGT;backuptype=full)" "zip64(level=1)" "local(path=C:\PlikiUdostepnione\Ksiegowosc\NaszeDane\AABackupy\Dzienne\msbp_BCKP_%DATE%_D_.dat)" 

sqlcmd -S WINSERVER\INSERTGT -Q "BACKUP DATABASE XYZ TO DISK = 'C:\PlikiUdostepnione\Ksiegowosc\NaszeDane\AABackupy\Dzienne\sqlcmd_BCKP_%DATE%_D_.dat' WITH NAME = 'XYZ_backup', FORMAT"


Innymi słowy robię testowe backupy za pomocą sqlcmd i msbp (przy najsłabszej kompresji). Plik sqlcmd - 170 MB czas oscyluje pomiędzy 50s a 3 min, msbp - 50MB, 3-10s. Czy to rozwiązanie jest wiarygodne, nie mam pojęcia, na pewno nie jest tak wytestowane jak sqlcmd. Ale jeśli sobie nie poradzę z przyspieszeniem działania sqlcmd (więcej rdzeni, pisanie na szybszy dysk?) to będzie to na 99% rozwiązanie na błyskawiczny awaryjny backup przy przejściu serwera na zasilanie z UPS.

3) Szymon i Jarek - absolutnie macie rację jeśli chodzi o usera "sa", tipy i sugestie. U nas sa jest zakorzeniony dość historycznie. Długo by o tym pisać. W uproszczeniu - taka konfiguracja jest podstawową "dostarczaną" przez InsERT i ich system FK i tak się ciągnie od bodaj 7 lat. W okolicy wakacji nastąpił ciąg awarii będący klasycznym przykładem praw Murphy'go. Każda kolejna awaria pogłębiała skutki poprzedniej i obnażała braki w naszym IT. Dość powiedzieć, że w trybie nagłym musiałem się zaprzyjaźnić z SQLem, Insertem, Płatnikiem, serwerami, routerami, OSami i jednocześnie odtwarzać zasoby z mniej lub bardziej archiwalnych kopii bezpieczeństwa. Ale koniec końców się udało i teraz w zasadzie zostało zapanowanie nad automatyzacją backupowania zasobów na serwerze, w tym omawianego tutaj SQLa i ew. dokończenie "uszczelniania dostępu". Na Win7 każdy użytkownik ma już swoje konto i hasło, są dodatkowi użytkownicy "funkcyjni" - a to skaner sieciowy, a to konto FTP itd i generalnie jestem chyba przygotowany do wyłączenia kolegi "sa" i oparcie się o autentykację windows, gdyby nie to, nie do końca wiem co i w jakich okolicznościach przestanie działać u... zdalnych księgowych :). Ale na 100% po załatwieniu kopii bezpieczeństwa "z wszystkiego" zajmę się i tym tematem. Chociaż womituję już kwestiami IT, bo jestem zwykłym użytkownikiem który zabawę z tajemnicami komputera skończył niemal ćwierć wieku temu na etapie Fortranu, Basica i Turbopascala :)adam tkocz edytował(a) ten post dnia 08.11.11 o godzinie 23:36
Adam Tkocz

Adam Tkocz Teraz już
właściciel, znaczy
katastrofa się
zbliża

Temat: backup za pomocą sqlcmd

No to koniec jest blisko. Napisałem działające (o dziwo!) batche i proszę o uwagi. Pierwszy to codzienny backup:
 SET _instancja="WINSERVER\INSERTGT"
SET _baza=platnik
SET _rodzaj=dzienny
SET _katalog=C:\PlikiUdostepnione\Ksiegowosc\NaszeDane\AABackupy\Dzienne\

sqlcmd -S %_instancja% -Q "BACKUP DATABASE %_baza% TO DISK = '%_katalog%BCKP_%_rodzaj%_%_baza%_%DATE%.dat' WITH NAME = '%_baza%_backup', FORMAT" -o %_katalog%temp.txt

ECHO "backup %_katalog%BCKP_%_rodzaj%_%_baza%_%DATE%.dat wykonany o %TIME%" >> %_katalog%temp.txt
ECHO "---" >> %_katalog%temp.txt
COPY /Y %_katalog%temp.txt + %_katalog%log.txt %_katalog%temp2.txt
COPY /Y %_katalog%temp2.txt %_katalog%log.txt

del /Q %_katalog%temp*.txt

Dalej, w tym samym batchu, ustawiam zmienną _baza na kolejne pozycje i powtarzam linijki odpowiedzialne za backup i logowanie. Batch ten został dodany do harmonogramu zadań codziennie po północy.

Niemal identyczne batche działają co tydzień, co miesiąc i w momencie braku zasilania - zmienia się tylko zmienna _rodzaj, docelowy _katalog oraz czas wykonania w harmonogramie - odpowiednio co tydzień i co miesiąc, a w przypadku wywalenia zasilania - batcha wywołuje usługa związana z UPS.

Dalej - batch mający kasować zbędne dane i synchronizować je z lokalizacją backupową:
 :: Kasowanie codziennych backupów starszych niż 7 dni 
SET _rodzaj=dzienny
SET _katalog=C:\PlikiUdostepnione\Ksiegowosc\NaszeDane\AABackupy\Dzienne\
forfiles /P %_katalog% /M *BCKP_%_rodzaj%*.* /C "cmd /c del /Q @path" /D -7

:: Kasowanie TYGODNIOWYCH backupów starszych niż 31 dni
SET _rodzaj=tygodniowy
SET _katalog=C:\PlikiUdostepnione\Ksiegowosc\NaszeDane\AABackupy\Tygodniowe\
forfiles /P %_katalog% /M *BCKP_%_rodzaj%*.* /C "cmd /c del /Q @path" /D -31

:: Synchronizacja z RAIDa na dysk Backupowy

SET _source=C:\PlikiUdostepnione\Ksiegowosc\NaszeDane\AABackupy\
SET _dest=B:\NaszeDane\AABackupySQL\

SET _what=/COPYALL /B /SEC /MIR
:: /COPYALL :: COPY ALL file info
:: /B :: copy files in Backup mode.
:: /SEC :: copy files with SECurity
:: /MIR :: MIRror a directory tree

SET _options=/R:0 /W:0 /LOG+:%_dest%log.txt /NFL /NDL
:: /R:n :: number of Retries
:: /W:n :: Wait time between retries
:: /LOG :: Output log file
:: /NFL :: No file logging
:: /NDL :: No dir logging

ROBOCOPY %_source% %_dest% %_what% %_options%

Działa już synchronizacja z RAIDa na inny fizyczny dysk, a docelowo będzie jeszcze dodatkowo na inny serwer, jak ceny dysków wrócą do "normy". Polecenie ROBOCOPY i opcje zerżnąłem wprost z internetu W efekcie jest "brzydki" log. Nie wiem natomiast czy działa kasowanie, bo musi się "nazbierać" trochę danych.

Ale jeśliby to zadziałało, to docelowo będę miał siedem dziennych backupów, 4-5 tygodniowych i dodatkowy co miesiąc. Te miesięczne, oraz ewentualne awaryjne już nie będą kasowane. Przy wielkościach plików moich baz nie stanowi to żadnego problemu - po roku przewiduję może 5 GB. Akurat na kopię na DVD.

Proszę o ew. uwagi.adam tkocz edytował(a) ten post dnia 16.11.11 o godzinie 10:14
Jarosław Kędzierski

Jarosław Kędzierski Admin od okienek

Temat: backup za pomocą sqlcmd

Hmm....

Nie jestem pewien.

Czy kopiujes/przenosisz tylko logi czy pliki backów także ?

Co się wydarzy, jeżeli polecenie Copy się nie powiedzie (bo np. zmienisz nazwę katalogu docelowego, albo odbierzesz uprawnienia) ?

Jeżeli backupy z jakichś powodów przestaną się wykonywać... to kasowanie nie jest chyba najlepszym wyjściem.

Może i to niezbyt ładne, ale jakoś u mnie zawsze to wyglądało bardziej w ten sposób, że usuwałem backup z cyfrą 7, a następnie robiłem zmieniałem nazwy, coś w stylu:

if exist backup-current.bak
del backup-7.bak
move backup6.bak backup7.bak
move backup5.bak ..backup6.bak
...
move backup-current.bak backup-1.bak

sqlcmd...
Adam Tkocz

Adam Tkocz Teraz już
właściciel, znaczy
katastrofa się
zbliża

Temat: backup za pomocą sqlcmd

Pliki backupów też się przenoszą. Dokładniej to cały katalog z backupami, łącznie ze skryptami nawet.

A właśnie, zapomniałem o wyłączeniu kasowania jeśli ilość plików jest mniejsza niż X. A właściwie to nie potrafiłem wymyślić sensownego, prostego rozwiązania. Będę dumał. Twoje rozwiązanie wydaje się sensowne. Pomyślę i spróbuję coś podobnego dodać.
Adam Tkocz

Adam Tkocz Teraz już
właściciel, znaczy
katastrofa się
zbliża

Temat: backup za pomocą sqlcmd

Przemyśliwuję i po prawdzie patrząc na cały proces to problem tkwi gdzie indziej. Zaczyna się tuż po komendzie kopiującej bazę do backupu.
Teraz sobie przypomniałem, że nie moglem znaleźć czy i jak SQLCMD ustawia ERRORLEVELS lub wysyła jakikolwiek inny sygnał o sukcesie/porażce.

To by był najprostszy temat. Jeśli backup odbył się bez błędów (mniemam, że wtedy sprawdzanie istnienia pliku na dysku jest tylko dodatkowym elementem) to wtedy sobie mogę w miarę spokojnie kasować pliki starsze niż określoną ilość dni. A w drugim batchu zostawić tylko synchronizację pomiędzy kolejnymi nośnikami.

Ale nie udało mi się na tę chwilę wykryć tego sygnału o nieudanym backupie.

Edytka - nie potrafię wywołać błędu. Np założyłem locka na docelowy katalog/plik. Backup się NIE wykonał, a ERRORLEVEL bez zmian
 sqlcmd -b -S %_instancja% -Q "BACKUP DATABASE %_baza% TO DISK = '%_katalog%BCKP_%_rodzaj%_%_baza%_%DATE%.dat' WITH NAME = '%_baza%_backup', FORMAT" -o %_katalog%temp.txt
IF errorlevel 0 (
echo "backup %_katalog%\BCKP_%_rodzaj%_%_baza%_%DATE%.dat wykonano poprawnie" >> %_katalog%\error.txt
) else (
echo "backup %_katalog%\BCKP_%_rodzaj%_%_baza%_%DATE%.dat NIEUDANY!!!" >> %_katalog%\error.txt
)
ECHO %errorlevel%
adam tkocz edytował(a) ten post dnia 16.11.11 o godzinie 16:07
Adam Tkocz

Adam Tkocz Teraz już
właściciel, znaczy
katastrofa się
zbliża

Temat: backup za pomocą sqlcmd

No to ja na ten moment skończyłem.
Batch działa następująco:
1) Sprawdza z grubsza poprawność parametrów, na tej podstawie ustawia odpowiednie katalogi
2) Wykonuje pełny backup zawierający w nazwie pliku rodzaj backupu, nazwę bazy, datę wykonania. Do pliku logu (na początku ;) dodaje odpowiedni wpis.
2a) Kopiuje najświeższy backup jako "czysty" awaryjny. Robię to, gdyż się okazało z niewiadomych na razie powodów, że "nadpisanie" backupu, nawet pełnego, trwa w moim przypadku około 4x szybciej, niż gdy nie ma pliku. Pozwoliło mi to odpuścić temat szybkiego backupu z kompresją za pomocą msbp.exe.
3) Po wykonaniu POPRAWNYM (wg logu) wykonaniu backupu batch kasuje pliki, jeśli są starsze niż... i jest ich więcej niż... Kasowanie też jest logowane.
4) Jeśli coś się nie uda, to batch wyświetla okienko z komunikatem.

Do poprawienia w przyszłości jest na pewno zastąpienie "zaszytych" w skrypcie ustawień parametrami przesyłanymi z zewnątrz - np. rodzaj backupu, czy graniczny wiek plików i ich ilość. Wtedy w harmonogramie zadań chodziłby ten sam skrypt, z różnymi parametrami. A na razie mam 3 wersje.
Chyba też lepiej byłoby gdyby batch sprawdzał w MS SQL (a nie wg zadanej z góry listy) poprawność nazwy bazy danych.
No i parę "estetycznych" poprawek bym zrobił, bo niektóre operacje wykonuję dookoła z powodu niewiedzy.

Ostatnie pytanie, jakie mi się nasuwa, to czy nie warto dopisać backupów SystemDatabases (master, model, msdb, tempdb). Czy to może ułatwić w przyszłości odtwarzanie danych?

Jeśli się komuś przyda to załączam poprawiony batch:
CLS
@@ echo off

SET _instancja="WINSERVER\INSERTGT"
SET _rodzaj=Dzienny
SET _MaxPlikow=7
SET _MaxWiek=7

SET _baza=platnik
CALL :rodzajOK
CALL :bazaOK
CALL :BackUp
CALL :Kasowanie

SET _baza=Studio
CALL :rodzajOK
CALL :bazaOK
CALL :BackUp
CALL :Kasowanie

:: tu można dodać kolejne bazy

goto :stop


:BackUp

SET _katalog=C:\PlikiUdostepnione\Ksiegowosc\NaszeDane\AABackupy\%_rodzaj%\
SET _katawaryjny=C:\PlikiUdostepnione\Ksiegowosc\NaszeDane\AABackupy\Awaryjny\
IF NOT EXIST "%_katalog%" MD "%_katalog%"
IF NOT EXIST %_katawaryjny% MD %_katawaryjny%

SET _data=%DATE%
SET _plik=%_katalog%BCKP_%_rodzaj%_%_baza%_%_data%.dat
sqlcmd -S %_instancja% -Q "BACKUP DATABASE %_baza% TO DISK = '%_plik%' WITH NAME = '%_baza%_backup', FORMAT" -o %_katalog%temp.txt
COPY %_katalog%temp.txt %_katalog%temperr.txt
ECHO "backup %_katalog%BCKP_%_rodzaj%_%_baza%_%DATE%.dat wykonany o %TIME%" >> %_katalog%temp.txt
ECHO "---" >> %_katalog%temp.txt
COPY /Y %_katalog%temp.txt + %_katalog%log.txt %_katalog%temp2.txt
COPY /Y %_katalog%temp2.txt %_katalog%log.txt

rem zdarzenia wylaczajace kasowanie starszych backupow
rem albo nie istnieje plik backupu albo log nie zawiera słowa "successfully"
SET _BackUpSukces=0
IF EXIST %_plik% SET _BackUpSukces=1
FIND /C "successfully" %_katalog%temperr.txt | FIND ": 0" 1>NUL && SET _BackUpSukces=0
IF %_BackUpSukces% EQU 0 MSG * "Cos poszlo nie tak. Nie powstal backup %_rodzaj% bazy @%_baza%@ w dniu %_data%, albo log.txt nie zawiera frazy 'successfully'"
COPY %_plik% %_katawaryjny%Awaryjny_%_baza%.dat
goto :eof

:Kasowanie

del /Q %_katalog%temp*.txt
FOR /f "tokens=*" %%P IN ('dir %_katalog%BCKP_%_rodzaj%_%_baza%_*.dat /A-d /b') do (set /a _IloscPlikow+=1)
IF %_BackUpSukces% EQU 0 goto :eof
IF %_IloscPlikow% LEQ %_MaxPlikow% goto :eof
IF %_rodzaj% EQU "Miesieczny" goto :eof
IF %_rodzaj% EQU "Awaryjny" goto :eof

FORFILES /P %_katalog% /M BCKP_%_rodzaj%_%_baza%_*.dat /D -%_MaxWiek% /C "cmd /C del /Q @file & ECHO 'skasowane dnia %_data%'>>temp.txt @file "
COPY /Y %_katalog%temp.txt + %_katalog%log.txt %_katalog%temp2.txt
COPY /Y %_katalog%temp2.txt %_katalog%log.txt

goto :eof

:rodzajOK
IF %_rodzaj% EQU Testowy goto :eof
IF %_rodzaj% EQU Awaryjny goto :eof
IF %_rodzaj% EQU Miesieczny goto :eof
IF %_rodzaj% EQU Tygodniowy goto :eof
IF %_rodzaj% EQU Dzienny goto :eof
MSG * "Nieprawidłowy rodzaj backupu. %_rodzaj% nierozpoznany." & goto :stop

:bazaOK
IF %_baza% EQU platnik goto :eof
IF %_baza% EQU Studio goto :eof
IF %_baza% EQU PlatArch goto :eof
MSG * "Nieprawidłowa baza danych. %_baza% nierozpoznana." & goto :stop

:stop
IF EXIST %_katalog%temp*.txt del /Q %_katalog%temp*.txt
EXIT /B
adam tkocz edytował(a) ten post dnia 01.12.11 o godzinie 10:33
Daniel N.

Daniel N. Senior IT Architect,
DBA

Temat: backup za pomocą sqlcmd

Hej,

>Ostatnie pytanie, jakie mi się nasuwa, to czy nie warto dopisać backupów >SystemDatabases (master, model, msdb, tempdb). Czy to może ułatwić w >przyszłości odtwarzanie danych?

Jak najbardziej warto backupować bazy systemowe, oczywiście oprócz bazy tempdb (której backup de facto nie przejdzie)

Poniżej art do poczytania
http://msdn.microsoft.com/en-us/library/ms190190.aspx

Pozdrawiam,
Daniel

konto usunięte

Temat: backup za pomocą sqlcmd

Bardzo fajny bat. Mam pytanie jak z powrotem podmienić plik dat na oryginalny. Kopiowanie 1 do 1 nic nie daje.

konto usunięte

Temat: backup za pomocą sqlcmd

Musisz wykonać operację przywracania bazy danych z pliku .dat. Masz kilka możliwości, m. in.:

1. Użyć SQL Server Management Studio i tak na odpowiedniej bazie operacja "Restore database".

2. Możesz użyć polecenia sql zgodnie z:
http://msdn.microsoft.com/en-us/library/ms186858.aspx

Sam plik .dat nie zachowuje fizycznej struktury oryginalnych plików bazy danych więc podmiana uszkodzonych plików nic nie da.

Temat: backup za pomocą sqlcmd

Witam
Może troszkę odgrzeję.Skrypt rzeczywiście bardzo fajny. Brakuje mi tylko do kompletu pakowania plików wynikowych np 7-zip'em? Pliki backupowe SQL pakują się dosyć znacznie. Sam nie bardzo wiem od czego zacząć. W którym miejscu wciąć pakera + weryfikację pliku archiwum.
pozdrawiam i proszę o jakąś wskazówkę

Adam T.:
No to ja na ten moment skończyłem.
Batch działa następująco:
1) Sprawdza z grubsza poprawność parametrów, na tej podstawie ustawia odpowiednie katalogi
2) Wykonuje pełny backup zawierający w nazwie pliku rodzaj backupu, nazwę bazy, datę wykonania. Do pliku logu (na początku ;) dodaje odpowiedni wpis.
2a) Kopiuje najświeższy backup jako "czysty" awaryjny. Robię to, gdyż się okazało z niewiadomych na razie powodów, że "nadpisanie" backupu, nawet pełnego, trwa w moim przypadku około 4x szybciej, niż gdy nie ma pliku. Pozwoliło mi to odpuścić temat szybkiego backupu z kompresją za pomocą msbp.exe.
3) Po wykonaniu POPRAWNYM (wg logu) wykonaniu backupu batch kasuje pliki, jeśli są starsze niż... i jest ich więcej niż... Kasowanie też jest logowane.
4) Jeśli coś się nie uda, to batch wyświetla okienko z komunikatem.

Do poprawienia w przyszłości jest na pewno zastąpienie "zaszytych" w skrypcie ustawień parametrami przesyłanymi z zewnątrz - np. rodzaj backupu, czy graniczny wiek plików i ich ilość. Wtedy w harmonogramie zadań chodziłby ten sam skrypt, z różnymi parametrami. A na razie mam 3 wersje.
Chyba też lepiej byłoby gdyby batch sprawdzał w MS SQL (a nie wg zadanej z góry listy) poprawność nazwy bazy danych.
No i parę "estetycznych" poprawek bym zrobił, bo niektóre operacje wykonuję dookoła z powodu niewiedzy.

Ostatnie pytanie, jakie mi się nasuwa, to czy nie warto dopisać backupów SystemDatabases (master, model, msdb, tempdb). Czy to może ułatwić w przyszłości odtwarzanie danych?

Jeśli się komuś przyda to załączam poprawiony batch:
CLS
@@ echo off

SET _instancja="WINSERVER\INSERTGT"
SET _rodzaj=Dzienny
SET _MaxPlikow=7
SET _MaxWiek=7

SET _baza=platnik
CALL :rodzajOK
CALL :bazaOK
CALL :BackUp
CALL :Kasowanie

SET _baza=Studio
CALL :rodzajOK
CALL :bazaOK
CALL :BackUp
CALL :Kasowanie

:: tu można dodać kolejne bazy

goto :stop


:BackUp

SET _katalog=C:\PlikiUdostepnione\Ksiegowosc\NaszeDane\AABackupy\%_rodzaj%\
SET _katawaryjny=C:\PlikiUdostepnione\Ksiegowosc\NaszeDane\AABackupy\Awaryjny\
IF NOT EXIST "%_katalog%" MD "%_katalog%"
IF NOT EXIST %_katawaryjny% MD %_katawaryjny%

SET _data=%DATE%
SET _plik=%_katalog%BCKP_%_rodzaj%_%_baza%_%_data%.dat
sqlcmd -S %_instancja% -Q "BACKUP DATABASE %_baza% TO DISK = '%_plik%' WITH NAME = '%_baza%_backup', FORMAT" -o %_katalog%temp.txt
COPY %_katalog%temp.txt %_katalog%temperr.txt
ECHO "backup %_katalog%BCKP_%_rodzaj%_%_baza%_%DATE%.dat wykonany o %TIME%" >> %_katalog%temp.txt
ECHO "---" >> %_katalog%temp.txt
COPY /Y %_katalog%temp.txt + %_katalog%log.txt %_katalog%temp2.txt
COPY /Y %_katalog%temp2.txt %_katalog%log.txt

rem zdarzenia wylaczajace kasowanie starszych backupow
rem albo nie istnieje plik backupu albo log nie zawiera słowa "successfully"
SET _BackUpSukces=0
IF EXIST %_plik% SET _BackUpSukces=1
FIND /C "successfully" %_katalog%temperr.txt | FIND ": 0" 1>NUL && SET _BackUpSukces=0
IF %_BackUpSukces% EQU 0 MSG * "Cos poszlo nie tak. Nie powstal backup %_rodzaj% bazy @%_baza%@ w dniu %_data%, albo log.txt nie zawiera frazy 'successfully'"
COPY %_plik% %_katawaryjny%Awaryjny_%_baza%.dat
goto :eof

:Kasowanie

del /Q %_katalog%temp*.txt
FOR /f "tokens=*" %%P IN ('dir %_katalog%BCKP_%_rodzaj%_%_baza%_*.dat /A-d /b') do (set /a _IloscPlikow+=1)
IF %_BackUpSukces% EQU 0 goto :eof
IF %_IloscPlikow% LEQ %_MaxPlikow% goto :eof
IF %_rodzaj% EQU "Miesieczny" goto :eof
IF %_rodzaj% EQU "Awaryjny" goto :eof

FORFILES /P %_katalog% /M BCKP_%_rodzaj%_%_baza%_*.dat /D -%_MaxWiek% /C "cmd /C del /Q @file & ECHO 'skasowane dnia %_data%'>>temp.txt @file "
COPY /Y %_katalog%temp.txt + %_katalog%log.txt %_katalog%temp2.txt
COPY /Y %_katalog%temp2.txt %_katalog%log.txt

goto :eof

:rodzajOK
IF %_rodzaj% EQU Testowy goto :eof
IF %_rodzaj% EQU Awaryjny goto :eof
IF %_rodzaj% EQU Miesieczny goto :eof
IF %_rodzaj% EQU Tygodniowy goto :eof
IF %_rodzaj% EQU Dzienny goto :eof
MSG * "Nieprawidłowy rodzaj backupu. %_rodzaj% nierozpoznany." & goto :stop

:bazaOK
IF %_baza% EQU platnik goto :eof
IF %_baza% EQU Studio goto :eof
IF %_baza% EQU PlatArch goto :eof
MSG * "Nieprawidłowa baza danych. %_baza% nierozpoznana." & goto :stop

:stop
IF EXIST %_katalog%temp*.txt del /Q %_katalog%temp*.txt
EXIT /B



Wyślij zaproszenie do