Dziwna awaria programu SQL Server ulega awarii podczas przesyłania do postaci numerycznej


20

Podczas pracy z C # Entity Framework zauważyłem awarię mojej instancji SQL Server.

Byłem w stanie wyśledzić to do tego stwierdzenia:

SELECT * FROM dbo.[TestTable]
where mpnr in (1099059904,
1038139906,
1048119902,
1045119902,
1002109903,
1117109910,
1111149902,
1063149902,
1117159902,
1116109904,
1105079905,
1012079906,
1129129904,
1103059905,
1065059905,
1091059906,
1110149904,
1129149903,
1083029905,
1080139904,
1076109903,
1010019902,
1058019902,
1060019903,
1053019902,
1030089902,
1018149902,
1077149902,
1010109901,
1011109901,
1000119902,
1023049903,
1107119909,
1108119909,
1106119909)

Tabela wygląda następująco:

CREATE TABLE dbo.[TestTable]([MPNR] [numeric](9, 0) NOT NULL)

Awaria występuje przy każdym uruchomieniu zapytania. Jeśli zmniejszę liczbę wartości w INklauzuli, to zadziała. (Oczywiście nie zwraca wierszy.)

Wiem, że wartości w INklauzuli są liczbami 10-cyfrowymi, a kolumna ma tylko 9 cyfr, ale nie powinno to prowadzić do awarii całej instancji SQL Server.

Moja wersja SQL Servera to 2008 R2 w 32-bitowym systemie Windows Server 2003.

Czy to znany błąd? Czy istnieje łatka dla programu SQL Server?


Komentarze nie są przeznaczone do rozszerzonej dyskusji; ta rozmowa została przeniesiona do czatu .
Paul White mówi GoFundMonica

Odpowiedzi:


20

Byłem w stanie zreperować na 2008 R1 SP3 10.00.5512, ale zainstalowałem najnowszą CU (14).

Przeglądając błędy naprawione w interweniujących wersjach, wygląda na to, że musisz uaktualnić do wersji zawierającej następującą poprawkę.

Naruszenie zasad dostępu po uruchomieniu zapytania zawierającego wiele stałych wartości w klauzuli IN w SQL Server 2008 lub SQL Server 2012

W 2008 R2 potrzebujesz co najmniej 9 CU dla SP1 lub CU 5 dla SP2.

Opis objawów jest dość krótki, ale wspomina o niedopasowanych typach danych

Po uruchomieniu zapytania zawierającego wiele stałych wartości w klauzuli IN w Microsoft SQL Server 2008, Microsoft SQL Server 2012 lub Microsoft SQL Server 2008 R2 może wystąpić naruszenie zasad dostępu.

Uwaga Aby problem mógł wystąpić, stałe w klauzuli IN nie mogą być dokładnie zgodne z typem danych kolumny.

Nie definiuje „wielu”. Z testów, które zrobiłem, podejrzewam, że może to oznaczać „20 lub więcej”, ponieważ wydaje się, że jest to punkt odcięcia między dwiema różnymi metodami szacowania liczności.

Katastrofa miała miejsce w ramach kilku metod wywoływanych przy CScaOp_In::FCalcSelectivity()użyciu nazw takich jak LoadHistogramFromXVariantArray()i CInMemHistogram::FJoin() -> WalkHistograms().

W przypadku 19 lub mniej różnych pozycji na liście metody te w ogóle nie były wywoływane. Podobny SQL Sever 2000 bug wspomina również ten punkt odcięcia jako znaczące.

Wypełnianie tabeli testowej 100 000 wierszy losowych danych testowych wartościami od 0 do 1047 i histogramem rozpoczynającym się w następujący sposób

+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
|            0 |          0 |     104 |                   0 | 1              |
|            8 |        672 |     118 |                   7 | 96             |
|           13 |        350 |     118 |                   4 | 87.5           |
|           18 |        395 |     107 |                   4 | 98.75          |
|           23 |        384 |      86 |                   4 | 96             |
|           28 |        371 |      85 |                   4 | 92.75          |
+--------------+------------+---------+---------------------+----------------+

Zapytanie

SELECT * FROM dbo.[TestTable]
where mpnr in (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19)
option (maxdop 1)

Pokazuje szacunkowe wiersze z 1856 r.

Jest to dokładnie to, czego można się spodziewać po uzyskaniu szacunkowych wierszy dla 19 predykatów równości indywidualnie i zsumowaniu ich.

+-------+----------------+-------+
| 1-7   | AVG_RANGE_ROWS | 96    |
| 8     | EQ_ROWS        | 118   |
| 9-12  | AVG_RANGE_ROWS | 87.5  |
| 13    | EQ_ROWS        | 118   |
| 14-17 | AVG_RANGE_ROWS | 98.75 |
| 18    | EQ_ROWS        | 107   |
| 19    | AVG_RANGE_ROWS | 96    |
+-------+----------------+-------+

7*96 + 118 + 4*87.5 + 118 + 4*98.75 + 107 + 1*96 = 1856

Formuła przestaje działać, gdy 20zostanie dodana do listy w ( wygenerowane zostaną szacunkowe wiersze, 1902.75a nie 1952dodanie tego 96do sumy).

BETWEEN wydaje się używać jeszcze jednej metody obliczania szacunków liczności.

where mpnr BETWEEN 1 AND 20szacuje tylko 1829,6 wierszy. Nie mam pojęcia, jak to wynika z pokazanego histogramu.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.