Witaj na Zine.net online Zaloguj się | Rejestracja | Pomoc

[PL] Prosto z frontu – linked server też może Cię zaskoczyć

Siedzę ostatnio u klienta i migruję bazy. Robota jak robota, trochę skryptowania, trochę robót ręcznych, trochę dokumentowania. Życie. Dzisiaj miałem jedną przygodę, o której pomyślałem, że warto ją opisać, bo najlepszy przyjaciel programisty – Google – nie pomógł mi i przeżyłem chwile niepewności :-)

Scenariusz prosty – dwie instacje SQL Server – jedna 2005, druga 2008. Na obu bazy danych, które odwołują się do baz z drugiego serwera. Czyli na każdej instancji tworzę linked server wskazujący na drugą instancję. Puszczam testowego SELECTa z obu stron – działa. Jakiś czas potem kolega mówi, że aplikacja korzystająca z baz wywala się na jednej z procedur z mniej więcej takim oto komunikatem:

OLE DB provider "SQLNCLI" for linked server "SERVER_A" returned message "Unspecified error".
Msg 7343, Level 16, State 2, Line 1
The OLE DB provider "SQLNCLI" for linked server "SERVER_A" could not INSERT INTO table "[SERVER_A].[DATABASE_A].[dbo].[TABLE_A]".

Hmmm… Pomyślałem, że coś źle z ustawieniami linked servera, ale nie, wszystko wydało się w normie. Puściłem więc Profilera, żeby wyłapać moment, kiedy to się wywraca. Wypadło na polecenie w stylu:

INSERT INTO [SERVER_A].[DATABASE_A].[dbo].[TABLE_A] (...) SELECT ... FROM [dbo].[TABLE_B]

przy czym TABLE_B jest na serwerze SERVER_B, z którego uruchamiam powyższe polecenie. Co ciekawe, chwilę przed tym poleceniem do tej samej zdalnej tabeli idzie polecenie DELETE, dodam, że wykonane z powodzeniem. Ale o so chosi???

Puszczam SELECT do tabeli zdalnej, działa. Puszczam sam INSERT (wcześniej szedł z procedury), nie działa (błąd jak wyżej). Hmmm…?

Dodam, że działam jako sysadmin na obu serwerach, więc o uprawnieniach mowy być nie może.

"Do ataku!" – pomyślałem. Zakładam swoją tabelkę w zdalnej bazie. INSERT do niej… działa! Hę???

Założyłem więc tabelę identyczną z tą, z którą był problem. INSERT i … taki oto kwiatek:

Msg 402, Level 16, State 1, Line 1
The data types void type and void type are incompatible in the is operator.

Powiało grozą… Przez głowę przeszła mi myśl, że znalazłem buga, który skutecznie powstrzyma mnie przed dokończeniem projektu w zadanym czasie albo co najmniej uprzykrzy mi życie w znacznym stopniu.

Ale, wiedziony doświadczeniem, spróbowałem "uszczuplić" utworzoną przez siebie tabelę, najpierw do jednej kolumny, a potem stopniowo dodając kolejne spróbowałem dojść do postaci, przy której INSERT zwraca któryś z błędów. Wreszcie, po dodaniu jednej z kolumn, INSERT zwrócił pierwszy ze wspomnianych błędów (7343). Uff… A więc namierzyłem winowajcę. Kolumna była typu użytkownika (nasz własny typ boolowski). Szybki rzut okiem na zawartość widoku sys.types powiedział mi, że typ ów wyróżnia się spośród innych typów jedynie tym, że została na niego nałożona reguła (obiekt typu RULE w bazie danych). Po zdjęciu reguły procedurą sp_unbindrule wszystko zaczęło śmigać!

Nasuwają się w zasadzie trzy pytania, na które absolutnie nie potrafię odpowiedzieć:

1. Dlaczego MS otwarcie nie pisze w BOL, że RULE nie nadają się do niczego, gdy mamy do czynienia ze środowiskami rozproszonymi (piszą jedynie, że kiedyś usuną obiekty RULE, ale to już widziałem dwie wersje temu)?

2. Skąd te typy void w komunikacie błędu 402?

3. Czy nie można było na okazję tego scenariusza opracować jasnego i oczywistego komunikatu, z którego mógłbym wywnioskować, jak postępować, zamiast tracić czas i nerwy na niekoniecznie interesujący research…?

Teraz zastanowię się, czy pisać cokolwiek o tym na Connect, bo przecież odpowiedź znam – cytując za BOL z sekcji CREATE RULE: "This feature will be removed in a future version of Microsoft SQL Server. Avoid using this feature in new development work, and plan to modify applications that currently use this feature. We recommend that you use check constraints instead. Check constraints are created by using the CHECK keyword of CREATE TABLE or ALTER TABLE." Znaczy się unsupported, obsolete, deprecated i w ogóle samo zło :-)

A więc do dzieła, idę założyć CHECK CONSTRAINT na każdej kolumnie używającej mojego fajnego typu (nie wspominam o parametrach i zmiennych w procedurach, funkcjach, triggerach). To nic, że mam jakieś 10 baz i kilka tysięcy obiektów w każdej z nich. Dobra, żartowałem, nie jestem aż tak nadgorliwy (i u mnie to jest "by design") :D

Opublikowane 29 stycznia 2009 22:27 przez brejk

Komentarze:

# re: [PL] Prosto z frontu – linked server też może Cię zaskoczyć

31 stycznia 2009 23:13 by can_do

Ja zastanawiam się, po co trzymają te rule przez jak to mówisz 2 wersje?

# re: [PL] Prosto z frontu – linked server też może Cię zaskoczyć

30 października 2009 14:58 by twrona

Dzięki.

Artykuł bardzo mi pomógł.

# [PL] AD MMIX – podsumowanie

23 grudnia 2009 09:12 by SQLGEEK

Kończy się rok 2009. Jak co roku postanowiłem więc podsumować te ostatnie trzysta parę dni i zdradzić

# re: [PL] Prosto z frontu – linked server też może Cię zaskoczyć

9 lipca 2010 02:47 by twilson@pobox.com

It is not just a problem with linked servers; it happens on a single server with two databases.

Komentarze anonimowe wyłączone

About brejk

MVP, MCT, SQL Server geek