Wiele razy zarówno na tym blogu jak i podczas rozmaitych spotkań "na żywo" obiecywałem, że w końcu VSS opiszę. Obietnice brały się głównie stąd, że VSS okazuje się całkiem użyteczną funkcjonalnością a tak naprawdę mało kto jej skutecznie i świadomie używa. Żeby nie pominąć niczego ważnego, postaram się przybliżyć VSS od sposobu jego działania aż po zastosowania praktyczne. Pominę za to część zagadnień związanych z wykorzystującymi VSS operacjami backup/restore wykonywanymi przez aplikacje. Od razu przepraszam za językowe potworki. Nie umiałem znaleźć polskich odpowiedników dla niektórych słów i zamiast kombinować, po prostu zostawiłem angielskie.
Od strony założeń, VSS przedstawia się stosunkowo prosto: dane na dysku składają się z bloków. Każdy odczyt danych to wczytanie bloku z woluminu a zapis – zapisanie go na dysk. Zapis danych na dysku nadpisuje dane, które w danym miejscu (na przykład w treści dokumentu) leżały wcześniej. A gdyby tak powiedzieć woluminowi, żeby przed nadpisaniem danego bloku wykonał jego kopię gdzieś na boku? Mielibyśmy zapisane wszystkie dane, ale równocześnie szansę na powrót do ich wersji sprzed ostatniego zapisu. Operujemy na blokach dlatego, że jeden plik zwykle ma wiele bloków, więc jeżeli zmieni się tylko jego fragment, to nie musimy kopiować tego, co i tak pozostaje na dysku bez zmian. Tak jest oszczędniej, a skoro dane w innych blokach się nie zmieniły, to i tak poskładamy z tego co mamy poprzednią wersję pliku.
Mniej więcej 10 lat temu, w systemie Windows XP, opisana powyżej idea została zaimplementowana w praktyce. Oczywiście, całość okazała się nie taka prosta, jak to na pierwszy rzut oka wygląda. Wprawdzie automatyczne przepisywanie nadpisywanych danych w specjalne miejsce nie jest niczym bardzo skomplikowanym, ale diabeł tkwi w dwóch szczegółach: w spójności i w interfejsach. Na początek interfejsy, bo to prostsze, przynajmniej na poziomie, na którym VSS poznać powinien typowy ITPro. Zasadniczo, chodzi o to, żeby mieć jak zarządzać tymi kopiami i mieć jak dotrzeć do starszych, teoretycznie nadpisanych już danych. Zarządzanie obejmuje takie aspekty jak na przykład ilość miejsca przeznaczonego na wykonane kopie czy też ich lokalizację. Dotarcie do danych zostanie jeszcze szerzej omówione, ale rzecz w tym, że proste podanie poprzedniej zawartości bloku to zwykle trochę za mało. Administrator czy użytkownik woli operować znanymi sobie pojęciami pliku, ścieżki czy folderu. Wiadomo, że pod spodem są bloki, ale z wyjątkiem bardzo specjalnych sytuacji, dostęp na tak głębokim poziomie jest zupełnie bezużyteczny.
Od razu dotknę kwestii miejsca na kopie nadpisanych bloków. W przypadku opisywanego tu systemowego mechanizmu, ilość miejsca określa administrator i jeżeli zostanie ono w całości wykorzystane, najstarsze kopie są nadpisywane. Może się przez to zdarzyć, że jakaś naprawdę istotna kopia zostanie zniszczona, bo w jej miejscu pojawią się świeższe kopie jakichś bzdetów, ale z drugiej strony nie bardzo jest jak podejść do tematu w inny sposób.
Spójność jest tematem dużo ciekawszym. Po pierwsze, w praktyce okazuje się, że zapisywanie każdego zmienionego bloku to trochę nieroztropne podejście. Są w systemie pliki, które zmieniają się co parę sekund, a są takie, gdzie zmiany zachodzą rzadko, za to sięgnięcie do ich starszych wersji ma dla użytkownika kluczowe znaczenie. Gdybyśmy zapisywali faktycznie każdy zmieniony blok, to albo kopiami zajmiemy bardzo dużo miejsca albo nadpiszemy to, co ważne. Osobiście wolę moje dokumenty w wersji sprzed tygodnia niż tysiące kopii folderu %temp%. Drugą kwestią jest dotarcie do tych danych, które mnie interesują. Jeżeli plik był nadpisywany dwieście razy (na przykład mechanizmami autosave), to czy naprawdę chcę mieć dwieście kopii? Poza tym, co w sytuacji, gdy potrzebuję odtworzyć więcej niż jeden plik, bo mam skorelowane ze sobą tabele, pliki konfiguracyjne czy cokolwiek innego, gdzie różne wersje pomiędzy plikami mogą być powodem kłopotów?
Żeby rozwiązać ten problem, w systemie Windows zastosowano podejście polegające na tworzeniu migawek (zwanych też przez niektórych snapshotami). To znaczy, nadpisane dane faktycznie kopiowane są w inne miejsce. Jednak jeżeli od pewnego momentu T, dane nadpisywane są ponownie – ich kolejna kopia archiwalna nie jest wykonywana. Jeżeli powiem, że moim momentem T jest godzina 00:00 każdego dnia, to pierwsze nadpisanie danych będzie wiązało się z zabezpieczeniem poprzedniej wersji. Kolejne już nie. Oznacza to, że tak często zmieniający się plik jak i mój ważny, ale tylko raz zmieniony dokument będzie miał w archiwum jedną kopię. Tę z północy. Podejście takie znacząco ogranicza rozmiar kopii archiwalnej i zmniejsza ilość operacji I/O. Dla często zmieniających się plików, kolejne zmiany w "normalny" sposób nadpisują bieżącą informację i nic nie jest kopiowane. Z drugiej jednak strony, oznacza to, że mogę stracić cały dzień pracy. Wprawdzie nadpisując o 16:59 mój raport dotrę do kopii wykonanej o północy, jednak nie mam wersji z 16:50, będącej wynikiem ośmiu godzin stukania w klawiaturę i skasowanej przez przypadek. Trudno. Coś za coś. Należy jednak pamiętać, że podana wcześniej godzina 00:00 to tylko przykład. Migawkę mogę wykonać tak często jak zechcę, oczywiście w granicach rozsądku, co w praktyce oznacza zwykle raz albo dwa razy dziennie. Pracę z całego dnia można zwykle wykonać jeszcze raz a zbyt częste migawki to więcej kłopotu niż korzyści. Cierpi na tym wydajność i zajmują miejsce, w efekcie skracając czas o jaki możemy się cofnąć w przeszłość dzięki naszym kopiom.
OK. Wiemy, że używamy migawek, czyli bloki archiwalne pochodzą z danego, określonego przez nas momentu w czasie. Byłoby to bardzo piękne, gdyby nie to, że dane na dysku cały czas "żyją". Jeżeli zapisujemy na dysku wielki arkusz Excela, to trwa to parę chwil. A jeżeli właśnie w tym czasie nadejdzie moment zrobienia migawki? Początek pliku w migawce ma zupełnie inne pochodzenie niż jego koniec. Złapaliśmy przecież aplikację w połowie pracy. Duża szansa, że taki archiwalny plik nie zechce się otworzyć w sytuacji, gdy będzie to najbardziej potrzebne. A jeżeli nie będzie to plik *.xlsx tylko baza Active Directory? Repozytorium WMI? Baza SQL? Wtedy okaże się, że cały misterny plan spalił na panewce, bo wprawdzie mamy wierną kopię z momentu T, za to jest to kopia bezużyteczna, bo aplikacja nie umie jej otworzyć. I tu przychodzi z pomocą mechanizm tak zwanych Writers.
Skoro istnieje ryzyko, że na przykład SQL nie odczyta swoich własnych plików zapisanych w momencie wykonania migawki, to warto byłoby jakoś zapobiec takiej sytuacji. Można do tego podejść na przykład w taki sposób, że z migawką poczekamy aż dane na dysku będą w takiej postaci, że odczytanie będzie możliwe. Tylko jak ten właściwy moment określić? Oczywiście najlepiej poinformowany o tym jest sam serwer SQL. Dlatego, system Windows wyposażony został w mechanizmy pozwalające na podłączanie się różnych aplikacji i usług "zainteresowanych" spójnością danych na dysku. Taka podłączona aplikacja rejestruje swój VSS Writer i od tej pory VSS będzie z nią rozmawiał. Rozmowa taka to tak naprawdę dwa ważne momenty wymiany informacji:
Dzięki temu, migawka wykonuje się tak naprawdę chwilę po zaplanowanym czasie, ale w praktyce nie jest to kłopotliwe. Gorzej, gdy do zgłoszenia przez aplikację, że informacje na dysku są dobre i spójne mija dużo czasu. Aplikacje mają na to dziesięć sekund, więc nie powinno zdarzyć się, ze źle napisany writer coś popsuje, ale jeżeli 10s to za krótko – migawka po prostu się nie wykona. Jest to o tyle ważne, że dopóki migawka nie zostanie zrobiona, system (przez wysłanie komunikatu o wdzięcznej nazwie IOCTL_VOLSNAP_FLUSH_AND_HOLD_WRITES) czasowo przestawia sterowniki pamięci masowych w tryb, w którym nowe dane nie są zapisywane. Wszystko dla spójności.
Jeżeli kogoś znużyło czytanie – może zrobić krótką przerwę i w wierszu poleceń wpisać sobie polecenie vssadmin list writers. Zobaczy wtedy ile w jego systemie jest chętnych na rozmowę z mechanizmami VSS.
Drugim określeniem, istotnym i pojawiającym się często w parze z VSS Writer, jest VSS Provider. W tym obszarze teoretycznych rozważań będzie mniej, bo VSS Provider, to ten, kto faktycznie wykonuje kopie archiwalne zmodyfikowanych bloków. Podejrzenie, że robi to przecież sam system operacyjny jest słuszne, ale istnieją przypadki (na przykład w zaawansowanych macierzach), gdy zajmuje się tym specjalny sprzęt. Ktoś to w każdym razie robić musi a VSS musi być pewny, że odpowiedzialny za kopiowanie danych provider wywiąże się ze swojego zadania. Tak naprawdę, od providera zależy jak to dokładnie się stanie, że zostanie zachowana archiwalna kopia danych. Kopiowanie zmienianych bloków do specjalnej lokalizacji to tylko jedna z metod. Systemowi Windows w żaden sposób nie zależy na szczegółach rozwiązania tak długo, jak długo do starszych danych da się dotrzeć. Skupimy się jednak na kopiowaniu zmienionych bloków (copy on write) dlatego, że ta właśnie metoda wbudowana została w systemowego providera (swprv.dll i volsnap.sys) i w efekcie, to właśnie z nią mamy najczęściej do czynienia. Provider ten kopiuje zmienione bloki do specjalnych plików, które dobrze schowane przed użytkownikiem znajdują się w folderze "System Volume Information" na każdym chronionym woluminie. Jeżeli kogoś *** obejrzenie ich bliżej, pomocny będzie psexec i wiersz poleceń uruchomiony w kontekście localsystem. Warto też pamiętać o parametrze "/a" polecenia dir. Co ciekawe (ale i oczywiste gdy się chwilę zastanowić), sam folder "System Volume Information" nie jest chroniony mechanizmami VSS. To samo dotyczy plików pagefile.sys i hiberfil.sys, co też ma swój sens. Gdyby ktoś chciał zobaczyć jacy providerzy w jego systemie troszczą się o dane, wystarczy w wierszy poleceń wpisać vssadmin list providers
Dla ścisłości, trzeba w tym miejscu wspomnieć o trzecim elemencie rozwiązań bazujących na VSS. Requestor, to tak naprawdę użytkownik VSS. Ktoś, kto zleca wykonanie migawki, ktoś kto do niej sięga, ktoś kto ją kasuje. Nic niezwykłego, ale dla pełnego obrazu piszę, że i taki element w świecie VSS się pojawia.
No i na koniec został koordynator, rozmawiający z writerami, providerami i requestorami. W systemie Windows ma on postać usługi systemowej, której szczegóły można zobaczyć po wydaniu w wierszu poleceń komendy sc qc vss. To on odpowiada za to, co się dzieje ale jak to z rolą zarządzającego bywa – jego działania są najmniej spektakularne.
Jak już wcześniej napisałem, migawki są widoczną realizacją całej idei zapewnienia dostępu do archiwalnych kopii danych. Migawka jest wykonywana na żądanie i potem można z niej skorzystać. I tu też okazuje się, że całość nie jest taka zupełnie prosta. Nie dlatego, że trzeba jeszcze jakieś techniczne detale uwzględnić, tylko dlatego że dla wygody użytkowników migawki występują w wielu różnych typach, różniących się zastosowaniami. W praktyce typowego ITPro wystarczy wiedzieć, że migawki dzielą się na takie, które po utworzeniu są widoczne i dostępne dla wszystkich i takie, do których dostęp ma tylko ich twórca. Dla migawek spotkać się można również z określeniami:
Ostatnie trzy określenia dotyczą widoczności migawek jako dysków i temu zagadnieniu poświęcę dalej jeszcze trochę miejsca. Jeżeli ktoś chce głębiej podrążyć temat typów migawek, powinien sięgnąć do MSDN i spojrzeć na _VSS_SNAPSHOT_CONTEXT i na _VSS_VOLUME_SNAPSHOT_ATTRIBUTES
Po nieco przydługim wstępie teoretycznym pora zrobić coś użytecznego – przygotować miejsce, w które systemowy provider przepisywać będzie oryginalne dane pierwszy raz zmodyfikowane od ostatniej migawki. W systemie Windows robi się to (tak jak i całą masę innych rzeczy związanych z VSS) poleceniem vssadmin. Żeby utworzyć miejsce na dane należy wiedzieć:
Administratorowi wiedzącemu trzy opisane powyżej rzeczy pozostaje wydanie polecenia vssadmin add shadowstorage /for=<ForVolumeSpec> /on=<OnVolumeSpec> [/maxsize=<MaxSizeSpec>]
Z czasem, wyznaczone miejsce się zapełni i najstarsze dane będą usuwane. Gdyby jednak ktoś chciał sprawdzić ile miejsca na kopie archiwalne jest zajęte – może to oczywiście zrobić: vssadmin list shadowstorage. Ewentualny tuning i zmiana ilości już zarezerwowanego miejsca też jest możliwa. Jak łatwo się domyślić, robi się to poleceniem vssadmin, tym razem z parametrami resize shadowstorage. Należy pamiętać, że zmniejszenie miejsca może spowodować skasowanie najstarszych kopii, jeżeli nowa ilość jest mniejsza niż niezbędna do przechowania tych migawek. Jeżeli ktoś stwierdzi, że miejsce na migawki w ogóle jest mu nie potrzebne, też może zrealizować swoje chęci wklepując vssadmin delete shadowstorage. Oczywiście przechowywane w tym miejscu migawki (wiem, że takie określenie to uproszczenie) przestają istnieć.
Podsumowując zarządzanie miejscem na migawki mamy:
Czyli w zasadzie wszystko, co może być potrzebne.
OK. Mamy miejsce na migawki (a tak naprawdę miejsce na archiwalne kopie bloków, które po połączeniu z blokami niezmienionymi dadzą nam pseudowolumin, z którego możemy odczytać dane), więc pora jakąś migawkę zrobić. Od strony administratora to proste, bo wystarczy, że powie, że migawkę chce mieć. Od strony systemu widać jednak, że dużo się musi wydarzyć nim migawka się pojawi. Powiedzenie systemowi "chcę migawkę teraz" sprowadza się do wydania polecenia vssadmin create shadow /for =<ForVolumeSpec> Można do tego jeszcze dodać parametr /autoretry, który będzie przez zadany czas próbował utworzyć migawkę, jeżeli pierwsza próba się nie uda. Dlaczego może się nie udać, napisałem już wcześniej, przybliżając ideę writera.
Sprawdzenie, czy migawka naprawdę istnieje i dowiedzenie się czegoś na jej temat nie jest wiele bardziej skomplikowane. Wystarczy wydać polecenie vssadmin list shadows, ewentualnie rozszerzając je o parametry ograniczające wyświetlane informacje. Dla każdej widocznej dla VSS migawki wyświetlone zostaną parametry zawierające między innymi:
Warto wiedzieć, że mechanizmy VSS nie zmieniły się bardzo mocno i dysk z migawkami można przenieść ze starego komputera do nowego, na przykład z systemem Windows 2008 R2 i nadal do migawek mieć dostęp.
Mamy już omówione tworzenie (create shadow) i przeglądanie (list shadows) migawek. Do kompletu potrzebne jest jeszcze ich kasowanie. Tu również dobrze sprawdza się vssadmin, tym razem w postaci vssadmin delete shadows. Jako parametry podajemy wolumin, dla którego kasujemy migawkę i dane migawki do skasowania. Możemy podać jej GUID (vssadmin delete shadows /for=<ForVolumeSpec> /shadow=<ShadowID>), określić że chcemy skasować najstarszą migawkę (vssadmin delete shadows /for=<ForVolumeSpec> /oldest) albo skasować dla danego woluminu wszystko hurtem (vssadmin delete shadows /for=<ForVolumeSpec> /all).
Należy przy tym pamiętać (wyszło to już przy okazji tworzenia zestawów migawek), że vssadmin to narzędzie bardzo przydatne, ale nie wszechmocne. Może się zdarzyć, że jego możliwości będą zbyt małe i na przykład nie skasuje nietypowej migawki albo nie powie wszystkiego, co chcielibyśmy wiedzieć. W takiej sytuacji należy sięgnąć po VSS SDK i użyć vshadow.exe.
Na koniec jeszcze jedna uwaga. Wspominałem (bo tak zazwyczaj się to robi), że migawki tworzone są na przykład automatycznie o północy każdego dnia. Nie ma tu żadnej magii ani tajemnej składni polecenia. Po prostu polecenie tworzące migawkę trzeba dodać do harmonogramu zadań zwanego też Task Schedulerem.
Migawki same dla siebie byłyby bezużyteczne, gdybyśmy nie mogli skorzystać z zawartych w nich danych. Możemy to względnie prosto zrobić, ale najpierw trzeba odczytać nazwę migawki. W zwracanym przez vssadmin list shadows tekście, nazwy migawek to te wpisy przypominające na przykład \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy27 Żeby taką migawkę zobaczyć jako pseudowolumin, możemy wybrać jedną z dwóch dróg:
Oczywiście nietrudno się domyślić, że z samej natury migawki wynika, że taki pseudo dysk będzie pracował w trybie tylko do odczytu. Ale dla potrzeb sięgnięcia po archiwalne dane to w zupełności wystarczy.
Zawsze powtarzam, że GUI jest dla mięczaków, ale skoro ktoś je wbudował w system, to nie wypada o nim nie wspomnieć. Dla potrzeb VSS interfejs graficzny istnieje i nie trzeba wszystkiego robić ręcznie wklepując polecenia w cmd.exe. Najistotniejsze parametry dostępne są po kliknięciu prawym przyciskiem myszy na woluminie i wybraniu z właściwości zakładki "Shadow Copies". Można tam ustawić położenie i rozmiar przestrzeni na kopie archiwalne, w prosty sposób ustalić harmonogram wykonywania kopii a także tworzyć, przeglądać i kasować migawki.
Od strony użytkownika, VSS objawia się jeszcze ciekawiej. Na każdym dysku sieciowym, dla którego na serwerze działa VSS i automatyczne wykonywanie migawek, użytkownik we właściwościach foleru ma prosty wgląd w dane zebrane na migawkach. Uciążliwe żonglowanie tasiemkami przez administratora ratującego użytkownika w sytuacji "mój plik zniknął" zostało zastąpione kilkoma kliknięciami, które użytkownik tak naprawdę może wykonać samodzielnie.
Jak każdy kawałek IT, tak i VSS może czasem sprawiać kłopoty. Nie bardzo istnieje prosta i uniwersalna porada, ale na pewno dobra diagnostyka przybliży do rozwiązania.
Dla VSS, GUID to 9138500e-3648-4edb-aa4c-859e9f7b7c38 i wartość ta może być potrzebna w drugim i trzecim przypadku.
Co dalej? To zależy. Jeżeli komuś nadal mało wiedzy – bardzo mocno zachęcam do pogrzebania po SDK i MSDN. Tam jest wszystko o może być potrzebne. Później już zaczynamy z tworzeniem własnych writerów, requesterów i providerów. Czyli wyższa szkoła jazdy i dużo programowania.
Warto jeszcze przy okazji wspomnieć, że z mechanizmów VSS dość mocno korzysta DPM, rozszerzając je między innymi o funkcjonalność gwarantowanego przechowywania migawek przez zadany czas. Trochę o szczegółach działania można się dowiedzieć na przykład tutaj.
Jak widać VSS to kawałek naprawdę ciekawych wnętrzności każdego współczesnego systemu Windows. Z własnego doświadczenia wiem, że w całej masie sytuacji (takich, których opis musiałby się zacząć od "Ups....!") pozwolił mi on uniknąć straty wielu godzin pracy. Dlatego warto poświęcić parę chwil żeby dobrze go poznać i zrozumieć, potem raz dobrze i świadomie ustawić a potem korzystać. Oby jak najrzadziej!
Autor: Grzegorz Tworek [MVP]
Grzesiek, jak zwykle milutka dawka internalsowej wiedzy, dzięki! :)
No dziękuję za miły komentarz. Ale że "internalsowej" to trochę przesada. Faktycznie nie wszystko, co opisałem widać w GUI, ale tak naprawdę to całkiem prosta i dostępna dla końcowego użytkownika funkcjonalność. Trochę tylko zmitologizowana i dlatego poczułem potrzebę jej opisania. ;)
Tak z nieco innej pary kaloszy: bawiles sie moze kiedys zfs-em?
Niestety nie.