DbContextPool yra nauja funkcija, pristatyta ASP.NET Core 2.1, kuri taupo pridėtines išlaidas kuriant DbContext egzempliorių, tačiau joje yra paslėpta nedidelė duobė. Neseniai "ASP.NET Core" projektas kurį laiką buvo vykdomas nepertraukiamai, o tada žurnaluose pasirodė klaida, kad duomenų bazės ryšių telkinys pasiekė maksimalų ryšių skaičių:
System.InvalidOperationException: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached. adresu System.Data.Common.ADP.ExceptionWithStackTrace(Išimtis e) Iš pradžių maniau, kad tai buvo kažkoks kodas, dėl kurio DbContext tinkamai disponavo, bet kode neradau jokių užuominų. Vėliau tikrai nebuvo ko abejoti, tik DbContextPool, todėl bandžiau pašalinti DbContextPool, bet klaida išnyko. Tai iš tiesų sukėlė DbContextPool, tačiau žmonės stebisi, kad DbContextPool iš pradžių buvo skirtas sutaupyti DbContext egzempliorių kūrimo pridėtines išlaidas, taigi kaip jis gali sunaudoti daugiau duomenų bazių ryšių, o šio projekto apkrova yra labai maža, kaip jis gali sunaudoti visą ryšio telkinį? Aš kalbėjau apie šią keistą problemą savaitės susitikime šiandien, ir tada aš staiga maniau, kad kiekvienas DbContext egzempliorius užims duomenų bazės ryšį (SqlConnection), ir kai DbContextPool nėra įjungtas, kai tik užklausa baigiasi, atitinkamas DbContext egzempliorius bus pašalintas, ir duomenų bazės ryšys bus įdėtas atgal į ryšio baseiną. Naudojant DbContextPool, DbContext nebus pašalintas, bet bus grąžintas į DbContextPool pasibaigus užklausai, o DbContext bus grąžintas atgal į savo telkinį, o tai reiškia, kad atitinkamas duomenų bazės ryšys nebus grąžintas į ryšių telkinį, kuriam jis priklauso. Kiekvienas DbContextPool DbContext atitinka duomenų bazės ryšį, o kiekvienam papildomam DbContext DbContextPool duomenų bazės ryšių telkinyje bus vienu duomenų bazės ryšiu mažiau. Kai du telkiniai yra skirtingo dydžio, o DbContextPool yra didesnis nei duomenų bazės ryšio telkinys, iškyla problema, DbContextPool laisvai užpildo DbContext į telkinį pagal savo telkinio dydį (tarkime, kad jis yra 128), nepaisydamas duomenų bazės ryšio telkinio dydžio (darant prielaidą, kad jis yra 100), o aukščiau pateikta klaida įvyks, kai bus užpildytas 101-asis DbContext. Šis projektas naudoja numatytuosius parametrus, ar numatytasis nustatymas sukelia šią problemą?
Žvelgiant į DbContextPool diegimo šaltinio kodą, numatytasis aptikimo telkinio dydžio apribojimas yra 128
Pažvelgę į "SqlConnention" diegimo šaltinio kodą, pamatysite, kad numatytasis ryšių telkinių dydžio apribojimas yra 100
Numatytasis nustatymas sukels problemą, o tai tikrai yra nedidelė spąstai.
Žinant priežastį, sprendimas yra paprastas, nustatykite DbContextPool poolSize į mažesnį nei duomenų bazės ryšio telkinio Max_Pool_Size
|