Mam skonfigurowaną grupę Always On Availability Group i chcę się upewnić, że moi użytkownicy używają ApplicationIntent = ReadOnly w swoich ciągach połączeń.
Czy z poziomu serwera SQL Server za pośrednictwem DMV (lub zdarzeń rozszerzonych itp.) Mogę stwierdzić, czy użytkownik połączony z ApplicationIntent = ReadOnly w swoim ciągu połączenia?
Proszę nie odpowiadać, w jaki sposób ZAPOBIEGAĆ połączeniom - nie o to chodzi w tym pytaniu. Nie mogę po prostu przerywać połączeń, ponieważ mamy istniejące aplikacje, które łączą się bez odpowiedniego ciągu, i muszę wiedzieć, które to są, aby móc współpracować z programistami i użytkownikami, aby stopniowo naprawić to z czasem.
Załóżmy, że użytkownicy mają wiele aplikacji. Na przykład Bob łączy się z SQL Server Management Studio i Excel. Łączy się z SSMS, gdy musi dokonać aktualizacji, i Excel, gdy musi dokonać odczytu. Muszę się upewnić, że używa ApplicationIntent = tylko do odczytu, gdy łączy się z programem Excel. (To nie jest dokładny scenariusz, ale jest wystarczająco blisko, aby to zilustrować.)
źródło
sqlserver.read_only_route_complete
ponieważ jest uruchamiany tylko na podstawowym.Odpowiedzi:
Biorąc pod uwagę
sqlserver.read_only_route_complete
Wydarzenie rozszerzone wspomniane przez Kin i Remusa, jest to miłe wydarzenie debugowania , ale nie zawiera ze sobą dużej ilości informacji - tylkoroute_port
(np. 1433) iroute_server_name
(np. Sqlserver-0.contoso.com) domyślnie . Pomogłoby to również ustalić, czy połączenie intencyjne tylko do odczytu zakończyło się powodzeniem. Wystąpiłoread_only_route_fail
zdarzenie, ale nie mogłem go uruchomić, może jeśli wystąpił problem z routingowym adresem URL, wydawało się, że nie został uruchomiony, gdy druga instancja była niedostępna / została zamknięta, o ile mogłem powiedzieć.Miałem jednak pewne sukcesy, łącząc to z
sqlserver.login
włączonym śledzeniem zdarzeń i przyczyn, a także pewnymi działaniami (takimi jaksqlserver.username
), aby były przydatne.Kroki ku reprodukcji
Utwórz sesję zdarzeń rozszerzonych, aby śledzić odpowiednie zdarzenia, a także przydatne działania i śledzić przyczynowość:
Uruchom sesję XE (rozważ próbkowanie, ponieważ jest to zdarzenie debugowania) i zbierz kilka danych logowania:
Uwaga tutaj sqlserver-0 jest moim czytelnym wtórnym, a sqlserver-1 podstawowym. Tutaj używam
-K
przełącznikasqlcmd
do symulacji logowania intencji aplikacji tylko do odczytu i niektórych loginów SQL. Zdarzenie tylko do odczytu jest uruchamiane po pomyślnym logowaniu tylko do odczytu.Po wstrzymaniu lub zatrzymaniu sesji mogę wykonać zapytanie i połączyć dwa zdarzenia, np .:
Kwerenda powinna pokazywać loginy z intencją aplikacji i tylko do odczytu:
read_only_route_complete
jest zdarzeniem debugowania, więc używaj oszczędnie. Rozważ na przykład pobieranie próbek.Próbowałem zmusić
pair_matching
cel do pracy, ale zabrakło mi czasu. Istnieje tutaj pewien potencjał rozwojowy, na przykład:źródło
Nie, nie wydaje się, aby istniała jakaś właściwość połączenia narażona na DMV (w sys.dm_exec_connections lub sys.dm_exec_sessions ) lub nawet CONNECTIONPROPERTY, która odnosi się do
ApplicationIntent
słowa kluczowego ConnectionString.Warto jednak poprosić, za pośrednictwem Microsoft Connect, o dodanie tej właściwości do
sys.dm_exec_connections
DMV, ponieważ wydaje się, że jest to właściwość połączenia przechowywanego gdzieś w pamięci SQL Server, w oparciu o następujące informacje znalezione na stronie MSDN dla Obsługa SqlClient dla wysokiej dostępności, odzyskiwania po awarii (moje wyróżnienie kursywą):Jeśli
USE
oświadczenie można zweryfikować, toApplicationIntent
musi istnieć poza początkową próbą połączenia. Jednak osobiście nie zweryfikowałem tego zachowania.PS Myślałem, że możemy wykorzystać fakty, które:
USE
instrukcji.Pomysł polegał na utworzeniu nowej bazy danych wyłącznie w celu przetestowania i śledzenia tego ustawienia. Nowa baza danych byłaby używana w nowej grupie dostępności, która byłaby ustawiona tak, aby zezwalała tylko na
READ_WRITE
połączenia. Teoria polegała na tym, że wewnątrz Logon Trigger,EXEC(N'USE [ReadWriteOnly]; INSERT INTO LogTable...;');
wewnątrzTRY...CATCH
konstrukcji, w której zasadniczo nic nie ma wCATCH
bloku, albo nie spowoduje błędu w połączeniach ReadWrite (które zalogują się w nowej bazie danych), aniUSE
nie spowoduje błędu w połączeniach ReadOnly, ale wtedy nic by się nie stało, ponieważ błąd jest wychwytywany i ignorowany (aINSERT
oświadczenie nigdy nie zostanie osiągnięte). W obu przypadkach faktyczne zdarzenie logowania nie zostanie zablokowane / odrzucone. Kod Logon Trigger byłby efektywnie następujący:Niestety, podczas testowania efektu wydania
USE
wyciągu wEXEC()
ramachTRY...CATCH
transakcji, stwierdziłem, że naruszenie dostępu to przerwanie na poziomie partii, a nie przerwanie na poziomie wyciągu. A ustawienieXACT_ABORT OFF
nic nie zmieniło. Stworzyłem nawet prostą Procedurę przechowywaną SQLCLR do użycia,Context Connection = true;
a następnie wywołałemSqlConnection.ChangeDatabase()
w ciągu a,try...catch
a transakcja była nadal przerywana. I nie można używaćEnlist=false
w połączeniu kontekstowym. A użycie zwykłego / zewnętrznego połączenia w SQLCLR, aby wyjść poza Transakcję, nie pomogłoby, ponieważ byłoby to zupełnie nowe Połączenie.Istnieje bardzo, bardzo niewielka możliwość, że zamiast instrukcji można użyć HAS_DBACCESS
USE
, ale tak naprawdę nie mam wielkich nadziei, że będzie w stanie uwzględnić bieżące informacje o połączeniu w swoich kontrolach. Ale nie mam też możliwości przetestowania tego.Oczywiście, jeśli istnieje flaga śledzenia, która może spowodować, że naruszenie dostępu nie przerywa partii, to wspomniany powyżej plan powinien działać ;-).
źródło
ROLLBACK
TriggerINSERT
logowania na tabelę dziennika :-)Jak bardzo chcesz być chory? Strumień TDS nie jest trudny do proxy, zrobiliśmy to dla naszej aplikacji SaaS. To, czego szukasz (dosłownie trochę), znajduje się w komunikacie login7. Możesz poprosić użytkowników o połączenie za pośrednictwem serwera proxy i zalogowanie / wyegzekwowanie bitu. Do diabła, możesz nawet włączyć dla nich. :)
źródło
Czy Twoja aplikacja używa konta usługi, czy może wielu kont usług? Jeśli tak, użyj Extended Event, aby monitorować ruch związany z logowaniem, ale wyklucz konta usług na podstawowym, zawsze aktywnym serwerze. Powinieneś być teraz w stanie zobaczyć, kto loguje się do podstawowego, zawsze dostępnego serwera i nie używa dodatkowego ciągu połączenia tylko do odczytu. Przygotowuję się do instalacji Always-On i właśnie to zrobię, chyba że powiesz mi, że to nie zadziała.
źródło
Niestety nie mam środowiska do przetestowania następujących elementów i niewątpliwie istnieje kilka punktów, w których może się nie powieść, ale wyrzucę to tam, gdzie jest warte.
Procedura składowana CLR ma dostęp do bieżącego połączenia za pośrednictwem
new SqlConnection("context connection=true")
konstrukcji (pobranej stąd ). Typ SqlConnection ujawnia właściwość ConnectionString . Ponieważ ApplicationIntent znajduje się w początkowym ciągu połączenia, przypuszczam, że będzie on dostępny w tej właściwości i można go przeanalizować. W tym łańcuchu jest oczywiście wiele hand-offów, więc mnóstwo okazji, aby wszystko miało kształt gruszki.Spowodowałoby to uruchomienie Logon Trigger, a wymagane wartości zachowywały się w razie potrzeby.
źródło