Posts tagged bug

[PL] SQL Server – Czy potrzebujemy master.dbo.sysprocesses?

VN:F [1.7.9_1023]
Rating: 5.0/5 (1 vote cast)

Na portalu connect,microsoft,com jednym ze zgłoszonych błędów jest ten zgłoszony przez Tony’ego Rogersona pt. Deprecation of sysprocesses – DMV’s doesn’t fully replace all columns. Od momentu, gdy w dokumentacji SQL Servera w opisie widoku sysprocesses (tak, to jest widok, ale piszą o nim, jakby to była tabela, jak za czasów SQL Servera 2000) pojawił się zapisek:

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.

rozgorzały dyskusje na temat słuszności posunięcia Microsoftu zmierzającego w kierunku wycięcia sysprocesses z przyszłych wersji SQL Servera. Głównym zarzutem zawsze było to, że widoki DMV, które Microsoft rekomenduje zamiast sysprocesses (konkretnie są to: sys.dm_exec_connections, sys.dm_exec_sessions, sys.dm_exec_requests) nie umożliwiają zwrócenia tych samych informacji, które można uzyskać odpytując sysprocesses. W szczególności nie można z ich pomocą dowiedzieć się, jakie sesje są podłączone do konkretnej bazy danych (np. w celu zamknięcia określonych połączeń poleceniem KILL), ponieważ nawet, jeśli w którymś z nich (sys.dm_exec_requests) pojawia się kolumna zawierająca identyfikator bazy danych, to niestety sensowne identyfikatory pojawiają się w niej tylko, gdy użytkownik używa obiektu proceduralnego, a nie pojawiają się w przypadku używania zapytań ad-hoc. Smaczku sprawie dodaje fakt, że Microsoft sam nadal wykorzystuje widok sysprocesses w zapytaniach zadawanych przez narzędzia najnowszych nawet wersji SQL Servera (np. Activity Monitor w SSMS 2008 R2 używa tego widoku do uzyskiwania listy sesji).

Paul White (aka SQLKiwi), świeżo upieczony SQL Server MVP i posiadacz arcyciekawego bloga (polecam!), podał obejście problemu z uzyskaniem przy użyciu DMV listy sesji podłączonych do konkretnej bazy danych:

SELECT request_session_id
FROM sys.dm_tran_locks
WHERE resource_type = N'DATABASE'
AND request_mode = N'S'
AND request_status = N'GRANT'
AND request_owner_type = N'SHARED_TRANSACTION_WORKSPACE'
AND resource_database_id = DB_ID(N'AdventureWorks');

Czy powyższe zapytanie zawsze zadziała poprawnie? Dla baz użytkownika, wg wszelkich przesłanek, tak. Testowałem różne warianty, poziomy izolacji i zapytanie zaproponowane przez Paula daje dobry wynik. Oczywiście, ciśnie się na usta pytanie, czemu nie można tego wyłuskać za pomocą trzech wspomnianych DMVs z rodziny sys.dm_exec_*. To pytanie do Microsoftu, na które chyba nikt w Redmond nie potrafi sensownie odpowiedzieć :-)

Analogiczne zapytanie z użyciem sysprocesses zwracające listę sesji podłączonych do bazy danych:

SELECT spid
FROM master.dbo.sysprocesses WITH (NOLOCK) -- asekuracyjny NOLOCK
WHERE spid > 50 -- choć ponoć spid > 50 nie zawsze oznacza sesję użytkownika
AND dbid = DB_ID(N'AdventureWorks');

A teraz zagadka na długi weekend. Dla jakich baz zapytanie Paula nie powie prawdy (nie pokaże pełnej listy podłączonych sesji, bo nie wykryje blokad typu SHARED_TRANSACTION_WORKSPACE)? Odpowiedzi możecie wpisywać w komentarzach do tego wpisu. Podpowiem, że akurat w przypadku tych baz raczej nikomu nie przyjdzie do głowy wycinać podłączonych sesji.

Miłego długiego majowego weekendu życzę :-)

[PL] SQL Server – Pierwsza impresja na temat SQL Server 2008 SP2

VN:F [1.7.9_1023]
Rating: 0.0/5 (0 votes cast)

Dzisiaj ukazała się aktualizacja Service Pack 2 dla SQL Servera 2008. Rzuciłem się na nią wygłodzony :-) Powód był dość oczywisty. Otóż pracując w poprzedniej  firmie (Asseco Business Solutions S.A.) zgłaszałem w ramach swojej pracy błąd, który bardzo przeszkadzał w implementacji mechanizmu wprowadzania zmian we własnych typach danych (patrz wpis na moim blogu: http://sqlgeek.pl/2010/01/04/en-call-for-voting-alter-type-in-sql-server/). Zatem pierwsze kroki w nowym buildzie (SQL Server 2008 SP2 otrzymał okrągły numerek 10.0.4000) skierowałem właśnie ku sprawdzeniu, czy nie występuje błąd opisany tu: Deadlock occurs when creating user-defined data type and objects that use it.

Okazało się, że prawie to naprawiono… A że prawie robi wielką różnicę, postanowiłem opisać, na czym polega owo “prawie”.

Co działa?

begin tran
create type a from int null
go 
create function b ()
returns int
as
begin
  declare @t table (c a null)
  return 1
end
go
commit

Przed SP2 taki kod zwracał komunikat mówiący o wystąpieniu zakleszczenia (deadlocka).

Świetnie! Good work, Microsoft! Niestety, moja euforia zgasła chwilę po tym, jak uruchomiłem powyższy kod. Marek Adamczuk podesłał mi informację, że u niego po zainstalowaniu SP2 błąd nadal występuje. Cytując klasyka, ale o so chosi?

Ano, rozchodzi się o to, że istnieje cała klasa podobnych problemów i nie o wszystkich przypadkach pomyślano w Redmond :-) Zobaczmy taki kod:

begin tran
create type a from int null
go
declare @t table (c a null)
go
commit

Wstawienie do transakcji zmiennej tabelarycznej wykorzystującej typ danych tworzony w tej samej transakcji spowoduje dokładnie ten sam błąd, co w opisywanym powyżej przypadku. Do przetestowania jest jeszcze kilka innych problemów, ale już teraz widać, jak trudno naprawić wszystkie problemy z transakcyjnością, jeżeli już pojawią się takowe w silniku bazodanowym (naprawienie takich błędów może implikować powstanie następnych, jako że są to zmiany wprowadzane niskopoziomowo w samym silniku).

Wypada jedynie testować dokładnie swój kod i liczyć, że Microsoft nadal będzie reagował na nasze zgłoszenia. W tym przypadku należy się cieszyć, bo jednak reakcja jest prawidłowa (wyeliminowano błąd opisany przeze mnie w zgłoszeniu). Nie wyeliminowano błędu analogicznego, ale nie zgłoszonego na portalu connect.microsoft.com. No cóż, trzeba zakasać rękawy i opisać i ten przypadek, by programiści mogli pogłówkować, czy warto ów błąd naprawiać i, ewentualnie, jak to zrobić :-)

[EN] Call for voting – ALTER TYPE in SQL Server

VN:F [1.7.9_1023]
Rating: 0.0/5 (0 votes cast)

Have you ever used an alias type in SQL Server? I bet you have. It’s really cool that you can create your own alias type with CREATE TYPE statement in your database and then use it in your database objects. What drives people to using the alias types is a thought that these types can be easily changed by a single operation which does not require looking into every individual database object and checking whether the alias type is used or not. Well, is this really the way it is? Unfortunately not.

There is no ALTER TYPE statement in SQL Server. So whenever you want to change your own alias type (for example to make it longer in case of variable length character types) you have to perform quite a lot of operations, like:

  • script and drop (or alter to make independent of the “altered” alias type) all procedural objects that use the “altered” alias type,
  • script and drop all constraints on columns of the “altered” alias type,
  • script and drop all foreign key referencing the columns mentioned above,
  • rename the “altered” alias type,
  • create the new alias type with the new definition and the old name of the “altered” alias type,
  • alter all columns of the “old type” to make them using the new alias type,
  • recreate all dropped objects and constraints,
  • refresh just recreated procedural objects.

That doesn’t look simple, does it? The bad news is that this is not all – you should perform all those operations in a single transaction… The reason is quite obvious – you are going to do some nasty things with the database objects (drops, alters, recreates). It would be bad if the process stopped somewhere in the middle (leaving some objects not restored to their original definitions). So, there is plenty of T-SQL code to write, all with transaction and error handling, dynamic T-SQL, lurking into metadata and so forth.

Unfortunately, there is a bug making all the operation practically impossible to perform in a single transaction in certain scenarios (when you use a table variable with a column of the “altered” alias type). See this item for details:
Deadlock occurs when creating user-defined data type and objects that use it

They promised to fix it in SQL Server 2008 R2. Just can’t wait to check it out (for now it’s not fixed in CTP).

My final point is to encourage you to voting for the item: MSFT-MSO: Support ALTER TYPE. This (ALTER TYPE statement) is something that I really wish to see in the next release of SQL Server. So please, vote for this item to be fixed/implemented. Let me know if you vote. Thanks in advance!