Haya ndiyo malalamiko niliyosikia kutoka kwa wasanidi wetu. Jambo la kufurahisha zaidi ni kwamba waligeuka kuwa wa kweli, na kusababisha uchunguzi wa muda mrefu. Hii inahusu seva za SQL tunazoendesha kwenye VMware.

Kwa kweli, ni rahisi kufanya seva ya uzalishaji kuanguka bila tumaini nyuma ya kompyuta ndogo. Tekeleza nambari ifuatayo (sio kwenye tempdb au kwenye hifadhidata iliyo na Uimara wa Kuchelewa kuwezeshwa):
set nocount on
create table _t (v varchar(100))
declare @n int=300000
while @n>0 begin
insert into _t select 'What a slowpoke!'
delete from _t
set @n=@n-1
end
GO
drop table _t
Kwenye eneo-kazi langu, inachukua sekunde 5, na kwenye seva ya uzalishaji, sekunde 28. Hii ni kwa sababu SQL inabidi isubiri logi ya muamala iandikwe kimwili, na tunafanya shughuli fupi sana hapa. Kwa kusema, tumeendesha lori kubwa, lenye nguvu katika trafiki ya jiji na tunatazama madereva wa utoaji wa pizza kwenye mbio za pikipiki kulipita—mapitio si muhimu hapa, kusubiri tu. Na hakuna hifadhi ya mtandao, bila kujali ni zero ngapi kwa bei yake, inaweza kupiga SSD ya ndani katika latency.
(Katika maoni, ilibainika kuwa nilidanganya-nilikuwa nimechelewesha uimara katika sehemu zote mbili. Bila uimara wa kuchelewa, inaonekana kama hii:
Eneo-kazi - sekunde 39, 15K tr/sec, 0.065ms /io kurudi na kurudi
PROD - sekunde 360, 1600 tr/sec, 0.6ms
Nilipaswa kugundua kuwa ilikuwa haraka sana)
Walakini, katika kesi hii, tunashughulika na sufuri ndogo za kazi ya Riemann zeta na mfano mdogo. Mfano ambao watengenezaji waliniletea ulikuwa tofauti. Nilishawishika kuwa walikuwa sahihi na nikaanza kuivua maelezo yake yote yanayohusiana na mantiki ya biashara. Wakati fulani, niligundua ningeweza kutupa nambari zao kabisa na kuandika yangu mwenyewe-moja ambayo inaonyesha shida sawa-lakini katika uzalishaji, inakwenda polepole mara 3-4:
create function dbo.isPrime (@n bigint)
returns int
as
begin
if @n = 1 return 0
if @n = 2 return 1
if @n = 3 return 1
if @n % 2 = 0 return 0
declare @sq int
set @sq = sqrt(@n)+1 -- check odds up to sqrt
declare @dv int = 1
while @dv < @sq
begin
set @dv=@dv+2
if @n % @dv = 0 return 0
end
return 1
end
GO
declare @dt datetime set @dt=getdate()
select dbo.isPrime(1000000000000037)
select datediff(ms,@dt,getdate()) as ms
GOIkiwa kila kitu kiko sawa, ukaguzi wa ubora utachukua sekunde 6-7-8. Hiki ndicho kilichotokea katika mfululizo. sevaLakini kwenye baadhi ya seva, ukaguzi ulichukua sekunde 25-40. Cha kufurahisha ni kwamba, hakukuwa na seva ambapo utekelezaji ulichukua, tuseme, sekunde 14—msimbo ulifanya kazi haraka sana au polepole sana, ikimaanisha kuwa tatizo lilikuwa, kwa kusema, nyeusi na nyeupe.
Nilifanya nini? Niliangalia vipimo vya VMware. Kila kitu kilikuwa sawa huko-kulikuwa na rasilimali nyingi, Muda Tayari = 0, kila kitu kilikuwa sawa, na wakati wa mtihani, wote kwenye seva za haraka na za polepole, CPU = 100 kwenye vCPU moja. Niliendesha jaribio la hesabu la Pi-matokeo yalikuwa sawa katika seva zote. Harufu ya uchawi ilizidi kuwa na nguvu.
Baada ya kufikia shamba la dev, nilianza kucheza na seva. Ilibadilika kuwa vMotion kutoka kwa mwenyeji hadi mwenyeji inaweza "kuponya" seva, lakini inaweza pia kugeuza seva "ya haraka" kuwa "polepole". Ilionekana kuwa ndivyo - baadhi ya wahudumu walikuwa na matatizo ... lakini ... hapana. Mashine moja pepe ilikuwa polepole kwenye seva pangishi, tuseme, A, lakini ilifanya kazi haraka kwa mwenyeji B. Mashine nyingine pepe, kwa upande mwingine, ilifanya kazi haraka kwenye A na kupunguza kasi kwenye B! Mashine zote mbili za "haraka" na "polepole" mara nyingi zilikuwa zikifanya kazi kwa mwenyeji mmoja!
Kuanzia wakati huo na kuendelea, kulikuwa na harufu tofauti ya sulfuri hewani. Tatizo halikuweza kuhusishwa na mashine ya mtandaoni (Viraka vya Windows, kwa mfano)—ilibadilishwa kuwa "haraka" wakati wa vMotion. Lakini tatizo pia halikuweza kuhusishwa na seva pangishi—inaweza kuwa na mashine za "haraka" na "polepole". Pia haikuhusiana na upakiaji—nilifanikiwa kupata mashine ya "polepole" kwenye seva pangishi, ambapo hapakuwa na kitu kingine chochote.
Kwa kukata tamaa, nilizindua Kichunguzi cha Mchakato wa Sysinternals na nikatazama safu ya SQL. Kwenye mashine polepole, mstari ambao ulivutia macho yangu mara moja ulikuwa:
ntoskrnl.exe!KeSynchronizeExecution+0x5bf6
ntoskrnl.exe!KeWaitForMultipleObjects+0x109d
ntoskrnl.exe!KeWaitForMultipleObjects+0xb3f
ntoskrnl.exe!KeWaitForSingleObject+0x377
ntoskrnl.exe!KeQuerySystemTimePrecise+0x881 < — !!!
ntoskrnl.exe!ObDereferenceObjectDeferDelete+0x28a
ntoskrnl.exe!KeSynchronizeExecution+0x2de2
sqllang.dll!CDiagThreadSafe::PxlvlReplace+0x1a20
… ruka
sqldk.dll!SystemThread::MakeMiniSOSTthread+0xa54
KERNEL32.DLL!BaseThreadInitThunk+0x14
ntdll.dll!RtlUserThreadStart+0x21
Hii ilikuwa tayari kitu. Programu iliandikwa:
class Program
{
[DllImport("kernel32.dll")]
static extern void GetSystemTimePreciseAsFileTime(out FILE_TIME lpSystemTimeAsFileTime);
[StructLayout(LayoutKind.Sequential)]
struct FILE_TIME
{
public int ftTimeLow;
public int ftTimeHigh;
}
static void Main(string[] args)
{
for (int i = 0; i < 16; i++)
{
int counter = 0;
var stopwatch = Stopwatch.StartNew();
while (stopwatch.ElapsedMilliseconds < 1000)
{
GetSystemTimePreciseAsFileTime(out var fileTime);
counter++;
}
if (i > 0)
{
Console.WriteLine("{0}", counter);
}
}
}
}Mpango huu ulionyesha kushuka kwa kasi zaidi: kwenye mashine "haraka", ilionyesha mizunguko milioni 16-18 kwa sekunde, wakati kwa polepole, ilikuwa milioni 1.5 au hata 700,000. Hiyo ni tofauti ya 10-20x (!!!). Huu ulikuwa ushindi mdogo: angalau hakukuwa na hatari ya kukwama kati ya usaidizi wa Microsoft na VMware, na wao kupitisha pesa.
Kisha maendeleo yalikwama-likizo, mambo muhimu, hysteria ya virusi, na ongezeko kubwa la kazi. Mara nyingi nilitaja tatizo la kichawi kwa wenzangu, lakini nyakati fulani ilionekana hata hawakuniamini—dai kwamba VMware ilikuwa inapunguza kasi ya nambari kwa mara 10-20 ilikuwa ya kuchukiza sana.
Nilijaribu kujua ni nini kilikuwa kinanipunguza mimi mwenyewe. Wakati fulani, nilifikiri ningepata suluhu—kuwasha na kulemaza Plugs Moto, kubadilisha ukubwa wa kumbukumbu, au idadi ya vichakataji mara nyingi ilifanya mashine kuwa "haraka." Lakini si milele. Kilichotokea kuwa kweli ni kwamba unachotakiwa kufanya ni kwenda nje na kugonga gurudumu-yaani, kulibadilisha. yoyote parameta ya mashine halisi
Hatimaye, wafanyakazi wenzangu wa Marekani ghafla walipata sababu ya msingi.

Waandaji walitofautiana katika masafa!
- Hili kwa ujumla si tatizo. Hata hivyo, wakati wa kuhama kutoka kwa seva pangishi hadi kwa seva pangishi yenye masafa tofauti, VMware lazima irekebishe matokeo ya GetTimePrecise.
- Hili kwa ujumla sio jambo kubwa isipokuwa unayo programu inayoomba wakati kamili mamilioni ya mara kwa sekunde, kama Seva ya SQL.
- Lakini hii sio jambo kubwa, kwani Seva ya SQL haifanyi hivi kila wakati (tazama Hitimisho)
Lakini kuna matukio wakati reki hii inapiga sana. Na ndiyo, kwa kugonga gurudumu (kubadilisha kitu katika mipangilio ya VM), nililazimisha VMware 'kuhesabu upya' usanidi, na mzunguko wa sasa wa mwenyeji ukawa mzunguko wa "asili" wa mashine.
uamuzi
Unapozima uboreshaji wa TSC, kusoma TSC kutoka ndani ya mashine pepe hurejesha thamani ya TSC ya mashine halisi, na kuandika TSC kutoka ndani ya mashine pepe hakuna athari. Kuhamisha mashine pepe hadi kwa seva pangishi nyingine, kuirejesha kutoka hali iliyosimamishwa, au kurejesha muhtasari husababisha TSC kuruka bila kuendelea. Baadhi ya mifumo ya uendeshaji ya wageni inashindwa kuwasha, au kuonyesha matatizo mengine ya kuhifadhi wakati, wakati uboreshaji wa TSC umezimwa. Hapo awali, kipengele hiki kilipendekezwa wakati mwingine ili kuboresha utendakazi wa programu zinazosoma TSC mara kwa mara, lakini utendaji wa TSC pepe umeboreshwa kwa kiasi kikubwa katika bidhaa za sasa. Kipengele hiki pia kimependekezwa kwa matumizi wakati wa kufanya vipimo vinavyohitaji chanzo mahususi cha muda halisi katika mashine pepe.
Kwa kifupi, unahitaji kuongeza parameter
monitor_control.virtual_rdtsc = FALSE
Hitimisho
Labda unashangaa: kwa nini SQL inahitaji kupiga simu kwa GetTimePrecise mara nyingi?
Sina nambari ya chanzo ya Seva ya SQL, lakini mantiki inaamuru hii. SQL ni karibu kama mfumo wa uendeshaji na ushirikiano wa sarafu, ambapo kila thread lazima mavuno mara kwa mara. Na ni wapi mahali pazuri pa kufanya hivi? Ambapo kuna kusubiri kwa asili - kufuli au IO. Sawa, lakini vipi ikiwa tunaendesha vitanzi vya hesabu? Kisha mahali dhahiri na karibu tu ni katika mkalimani (si kweli mfasiri), baada ya kutekeleza kauli inayofuata.
Seva ya SQL haitumiwi kwa hesabu safi, na hiyo sio shida. Walakini, vitanzi vinavyohusisha majedwali ya muda (ambazo huhifadhiwa mara moja) hubadilisha msimbo kuwa mlolongo wa taarifa zinazotekelezwa kwa haraka sana.
Kwa njia, ukifunga kazi katika NATIVELY COMPILED, huacha kuuliza, na kasi yake huongezeka mara kumi. Lakini vipi kuhusu shughuli nyingi za ushirika? Kwa nambari iliyojumuishwa asili, ilinibidi kuwezesha PREEMPTIVE MULTITASKING katika SQL.
Chanzo: mapenzi.com
