MS SQL Server 2005 Database Mirroring Automatic Failover – მწარე რეალობა…

დამატებულია: სამშაბათი, 28 ოქტომბერი, 2008
კატეგორიები: მონაცემთა ბაზები
ტეგები: , , ,
ნანახია: 1,316-ჯერ

2009 წელი კარს მოგვდგომია და ის დროა MS SQL 2008–ს ახალი შესაძლებლობებით აღფრთოვანებულები ტაშის კვრაში ვიყოთ, მაგრამ პირადად მე MS SQL 2005–ის შესაძლებლობებში გაპარული ლაფსუსებით უფრო ვარ იმედგაცრუებული.

შეცდომა ვის არ მოსვლიაო ნათქვამია და არც Microsoft–ია გამონაკლისი, კაცმა რომ თქვას არც შეცდომაა ისეთი კრიტიკული, რომ ორგანიზაციის ფუნქციონირებას რეალური საფრთხე შეუქმნას, მაგრამ მაინც გულდასაწყვეტია, რომ პროგრამულ კოდში გაპარული პაწია შეცდომის გამო დეველოპერები იძულებული ხდებიან არ გამოიყენონ მთელი სიძლიერით MS SQL 2005-ის ისეთი მშვენიერი  საშუალება, როგორიც გახლავთ Automatic Failover–ი გააქტიურებული Mirroring–ისას.

ძალიან რომ არ დაგაბნიოთ ტერმინებით, პირდაპირ საქმეზე გადავიდეთ. მოკლედ არსებობს ქვეყნად მონაცემთა ბაზების სერვერი სახელად Microsoft SQL Server 2005. თავისი წინამორბედისაგან განსხვავებით, ამ ვერსიაში უამრავი სიახლე და სასიამოვნო ინოვაციაა განხორციელებული, მათ რიცხვს განეკუთვნება ე.წ. Database Mirroring–იც. დეტალური ინფორმაცია ამ საშუალების შესახებ შეგიძლიათ ამ ბმულზე იხილოთ. მოკლედ ავხსნი რას ეხება ეს ახალი საშუალება და როდის შეგვიძლია გამოვიყენოთ.

წარმოიდგინეთ,  რომ გვაქვს მონაცემთა ბაზების სერვერი A რომელიც მაღალი დატვირთვის ქვეშ მუშაობს, ასევე წარმოიდგინეთ, რომ მონაცემთა ბაზების სერვერის თუნდაც რამოდენიმე წუთით გაჩერება სერიოზულ დარტყმას აყენებს კომპანიის ბიზნესს და ყველანაირად აუცილებელია ამ მოვლენის თავიდან აცილება. SQL 2005 გვთავაზობს საშუალებას, რომელიც გვეხმარება მინიმუმამდე დავიყვანოთ ან საერთოდ ავიცილოთ თავიდან მონაცემთა ბაზების სერვერის გაჩერების დრო. როგორ მუშაობს ეს ყველაფერი:

დავარქვათ ჩვენს მთავარ სერვერს A, ხოლო სარეზერვო სერვერს კი B. ორივე სერვერზე გაშვებულია SQL Server 2005 და გვაქვს ბაზა სახელად CriticalDB. ამ შემთხვევაში, Database Mirroring–ის ტერმინოლოგიით, სერვერი A წარმოადგენს Principal–ს, ხოლო სერვერი B Mirror–ს. იდეა და აზრი იმაშია, რომ ბაზა CriticalDB მუშაობს A სერვერზე, მაგრამ თუ რაიმე მიზეზით A სერვერზე პრობლემა წარმოიქმნა, რის გამოც წვდომა CriticalDB-ზე შეიზღუდა, კლიენტები მუშაობას აგრძელებენ B სერვერზე ისე, რომ პროცესი არ ჩერდება და ვერავინ გრძნობს ძირითადი სერვერის ჩავარდნას. ანუ სხვაგვარად რომ ვთქვათ, A და B სერვერები ისე ადუბლირებენ ერთმანეთს, რომ მომხმარებელი ამის შესახებ ვერაფერს იგებს, სისტემა კი 24/7 მუშა მდგომარეობაშია, მაგარია არა? :)

არსებობს Mirroring–ის 3 რეჟიმი, ესენია: High Availability, High Protection და High Performance. მეორე და მესამე რეჟიმების განხილვას გვერდით გადავდებ, რადგან ამ თემის აზრი ეგ არ არის და მაგაზე წერა შორს წაგვიყვანს, ჩვენთვის საინტერესო High Availability რეჟიმია და სწორედ მას განვიხილავთ. მოდით მოკლედ გავარკვიოთ რას ნიშნავს ეს რეჟიმი:

იმისათვის, რომ Database Mirroring-ი High Availability რეჟიმში ვამუსაოთ, აუცილებელია მესამე სერვერი C, იგივე Witness სერვერი. მისი ამოცანაა აკონტროლოს A და B სერვერები, მოახდინოს სინქრონიზაცია და საჭიროების შემთხვევაში მოახდინოს სერვერებს შორის ავტომატური გადართვა. ანუ გვაქვს სამ სერვერიანი არქიტექტურა, სადაც A სერვერი მთავარი, სამუშაო სერვერია, B სერვერი სარეზერვო, ხოლო C კი მაკონტროლებელი. როცა კლიენტი ცდილობს მოახდინოს ჩაწერა ბაზაში CriticalDB, ირკვევა რომ ეს ბაზა აქტიურია მთავარ, A სერვერზე და ჩანაწერის დამატება ხდება ამ სერვერის CriticalDB ბაზაში. ამავდროულად, ხდება იგივე ჩანაწერის სინქრონული ჩამატება B სერვერზე და ეს პროცესი ტრანზაკციულია, ანუ A სერვერზე ჩანაწერის ფიქსაცია ხდება მხოლოდ მას შემდეგ, რაც B სერვერი გვაძლევს პასუხს, რომ ყველაფერი რიგზეა. ახლა წარმოვიდგინოთ, რომ A სერვერი მწყობრიდან გამოვიდა, ქსელი გაეთიშა, ვინჩსტერი დაეწვა, ან ყველაფერი რიგზეა, უბრალოდ კონკრეტულად CriticalDB ბაზა დაზიანდა A სერვერზე, ამ დროს იწყება ყველაზე მთავარი! B სერვერის ბაზა CriticalDB გამოდის რეჟიმიდან Mirroring და გადადის რეჟიმში Principal და კლიენტების მიმართვები ავტომატურად მიდის უკვე არა A არამედ B სერვერთან. ამავდროულად, ხდება ყველა ცვლილების (Insert, Update, Delete) ფიქსაცია B სერვერზე რათა შემდეგ მოხდეს სინქრონიზაცია A სერვერთან. როგორც კი A სერვერის ფუნქციონალურობა აღდგება, B სერვერზე არსებული ცვლილებები აისახება A სერვერის CriticalDB ბაზაში და როცა A და B სერვერებზე ბაზები სინქრონული იქნება, ისინი კვლავ გაცვლიან როლებს და A სერვერი ისევ Principal–ი გახდება.

ყველაფერი ლამაზი და მარტივია. მინდა გაგახაროთ და გითხრათ, რომ ეს ყველაფერი მარტო ფურცელზე კი არა, რეალობაშიც მუშაობს :D  და თან საკმაოდ კარგად. აბა რაღა მინდა და რას გერჩით ან თქვენ ან Microsoft–ს? ახლავე აგიხსნით. ყველაფერთან ერთად, Microsoft–მა გადაწყვიტა, რომ კიდევ ერთი თავისტკივილი აეცილებინა ჩვენთვის და კეთილ დეველოპერებს, ერთი არაჩვეულებრივი საშუალება მოგვცა: თუ ბაზაზე გააქტიურებულია Mirroring–ი, მაშინ თქვენ, შეგიძლიათ დაწეროთ .NET–ზე პროგრამა, რომელსაც ConnectionString–ში მიეთითება როგორც ძირითადი, ისე სარეზერვო სერვერების მისამართები და თუ გაშვებულ პროგრამაზე, შუა მუშაობაში, ძირითადი სერვერი მწყობრიდან გამოვა, პროგრამა ავტომატურად ისე გადაერთვება და გააგრძელებს მუშაობას სარეზერვო სერვერზე, რომ კლიენტი ამის შესახებ საერთოდ ვერაფერს გაიგებს! მაგარია არა? :) მაგარია, მართლა მაგარია! როგორი სახე აქვს ასეთ Connection String-ს:

Data Source=ServerA;Failover Partner=ServerB;Initial Catalog=CriticalDB;Integrated Security=True;

როგორც ხედავთ ყველაფერი მარტივია, Connection String-ს დაემატა ერთადერთი პარამეტრი და პროგრამაც უკვე უფრო “ჭკვიანია” და იცის, რომ თუ ძირითად სერვერზე რაიმე პრობლემაა, ავტომატურად უნდა გააგრძელოს მუშაობა საერზერვოსთან. და აი აქ იწყება პრობლემა… პროგრამა არ აგრძელებს მუშაობას სარეზერვო სერვერთან… :(

დიდი კვლევა ძიების შემდეგ გაირკვა, რომ:

  1. თუ პროგრამის გაშვების მომენტში აქტიურია მთავარი, A სერვერი, და პროგრამის მუშაობისას მოხდა მისი მწყობრიდან გამოსვლა, პროგრამა ცდილობს დაუკავშირდეს B სერვერს, მაგრამ გაუგებარი მიზეზებით ვერ ახერხებს ამას და აგდებს შეცდომას - გამოსავალია პროგრამის გამორთვა და ჩართვა, მაშინ ის უკვე B სერვერთან ახდენს კავშირის დამყარებას და ყველაფერი რიგზეა. მაგრამ მთელი ხიბლი იმისა, რომ პროგრამა მუშაობის პროცესში ავტომატურად გადაერთვება ერთი სერვერიდან მეორეზე, დაიკარგა :(
  2. თუ პროგრამის გაშვების მომენტში აქტიურია სარეზერვო, B სერვერი, მაშინ პროგრამა იწყებს მასთან მუშაობას. თუ მუშაობისას ძირითადი სერვერი დაუბრუნდა სამუშაო მდგომარეობაზე და კვლავ თავის თავზე აიღო მთავარი სერვერის (Principal) როლი, პროგრამა ავტომატურად ახდენს B-დან A-ზე გადართვას ისე, რომ ამის შესახებ მომხმარებელი ვერაფერს იგებს, და ეს ყველაფერი რეალურ დროში!

ანუ აღმოჩნდა, რომ რაღაც ნახევრად ფუნქციონალური საშუალება გვაქვს, თუ პროგრამა მთავარი სერვერიდან იწყებს მუშაობას, მაშინ ავტომატური გადართვა ვერ ხერხდება, თუ დამხმარედან, მაშინ ხერხდება… მიზეზები დიდხანს ვეძიე და ბოლოს მივადექი ოფიციალურ Bug-ს, რომელიც იწვევს მთელი ამ სცენარის წყალში ჩაყრას. Bug-ი .NET Framework-ის ერთ-ერთ dll-შია გაპარული და რატომღაც მისი გამოსწორება ჯერ-ჯერობით თავშიც არავის მოსდის, შედეგად გვაქვს პროგრამული პროდუქტის უწყვეტად მუშაობის არაჩვეულებრივი მექანიზმი, რომელსაც… ვერ ვიყენებთ :)

რას იზამ, Microsoft-ია ;)

P.S. თუ ვინმეს ჰქონია შეხება მსგავს პრობლემასთან და რაიმე გადაწყვეტა აღმოაჩინა, ან რაიმე მიზეზებით ეს ყველაფერი ვინმესთან მუშაობს, სიამოვნებით მოვისმენ თქვენს აზრს :)

  1. Giorgi Dalakishvili
    28/10/2008 at 11:22

    საინტერესოა :)
    რა მოხდება იმ შემთხვევაში თუ პროგრამისას აქტიურია სარეზერვო B სერვერი, შემდეგ ძირითადი სერვერი A დაუბრუნდა სამუშაო მდგომარეობას და მერე ისევ გაითიშა A? ამ შემთხვევაში კვლავ რესტარტი უნდა პროგრამას?

  2. Giorgi Dalakishvili
    :

    საინტერესოა :)
    რა მოხდება იმ შემთხვევაში თუ პროგრამისას აქტიურია სარეზერვო B სერვერი, შემდეგ ძირითადი სერვერი A დაუბრუნდა სამუშაო მდგომარეობას და მერე ისევ გაითიშა A? ამ შემთხვევაში კვლავ რესტარტი უნდა პროგრამას?

    ჰო, მაგის დაწერა დამავიწყდა, შენს მიერ აღწერილი სცენარიც არ მუშაობს, ანუ თუ B სერვერიდან გადმოერთო A სერვერზე და მერე A ისევ ჩავარდა, პროგრამის რესტარტის გარდა არაფერი შველის საქმეს :(

  3. თუ Connection String-ში არ მივამატებთ Failover Partner-ს? მაშინ ალბათ C სერვერმა უნდა უნდა უზრუნველყოს ავტომატური გადართვა A->B და პირიქით B->A-ზე
    როცა მიერთება არა ADO.NET-ით ხდება, არამედ ჩვეულებრივი ADO-თი, მაშინ როგორ მუშაობს ეს მექანიზმი?