DbContextPool ir jauna funkcija, kas ieviesta ASP.NET Core 2.1, kas ietaupa DbContext instances izveides pieskaitāmās izmaksas, bet tajā ir paslēpta neliela bedre. Nesen ASP.NET Core projekts kādu laiku darbojās nepārtraukti, un pēc tam žurnālos parādījās kļūda, ka datu bāzes savienojuma baseins sasniedza maksimālo savienojumu skaitu:
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. vietnē System.Data.Common.ADP.ExceptionWithStackTrace(Izņēmums e) Sākumā es domāju, ka tas bija kāds kods, kas izraisīja DbContext pareizu iznīcināšanu, bet kodā es neatradu nekādas norādes. Vēlāk patiešām nebija ko apšaubīt, tikai DbContextPool, tāpēc es mēģināju noņemt DbContextPool, bet kļūda pazuda. To patiešām izraisīja DbContextPool, bet tas, kas liek cilvēkiem brīnīties, ir tas, ka DbContextPool sākotnēji ir paredzēts, lai ietaupītu DbContext instanču izveides pieskaitāmās izmaksas, tāpēc kā tas var patērēt vairāk datu bāzes savienojumu, un šī projekta slodze ir ļoti zema, kā tas var patērēt visu savienojuma baseinu? Es runāju par šo dīvaino problēmu šodienas iknedēļas sanāksmē, un tad es pēkšņi domāju, ka katra DbContext instance aizņems datu bāzes savienojumu (SqlConnection), un, ja DbContextPool nav iespējots, tiklīdz pieprasījums beigsies, atbilstošā DbContext instance tiks iznīcināta, un datu bāzes savienojums tiks ievietots atpakaļ savienojuma pūlā. Izmantojot DbContextPool, DbContext netiks iznīcināts, bet pēc pieprasījuma beigām tiks ievietots atpakaļ DbContextPool, un DbContext tiks ievietots atpakaļ savā pūlā, kas nozīmē, ka atbilstošais datu bāzes savienojums netiks atgriezts savienojuma pūlā, kuram tas pieder. Katrs DbContext DbContextPool atbilst datu bāzes savienojumam, un katram papildu DbContext DbContextPool datu bāzes savienojuma pūlā būs par vienu datu bāzes savienojumu mazāk. Ja abi baseini ir dažāda izmēra un DbContextPool ir lielāks par datu bāzes savienojuma pūlu, rodas problēma, DbContextPool brīvi aizpilda DbContext baseinā atbilstoši sava baseina lielumam (pieņemsim, ka tas ir 128), ignorējot datu bāzes savienojuma pūla lielumu (pieņemot, ka tas ir 100), un iepriekš minētā kļūda radīsies, kad tiek aizpildīts 101. DbContext. Šis projekts izmanto noklusējuma iestatījumus, vai noklusējuma iestatījums izraisa šo problēmu?
Aplūkojot DbContextPool ieviešanas avota kodu, atklāšanas pūla noklusējuma lieluma ierobežojums ir 128
Aplūkojot SqlConnention ieviešanas avota kodu, jūs atradīsit, ka savienojumu pūļu noklusējuma lieluma ierobežojums ir 100
Noklusējuma iestatījums izraisīs problēmu, kas patiešām ir neliela kļūda.
Zinot iemeslu, risinājums ir vienkāršs, iestatiet DbContextPool poolSize mazāku par datu bāzes savienojuma pūla Max_Pool_Size
|