DbContextPool on uus funktsioon, mis tutvustati ASP.NET Core 2.1-s ja mis säästab DbContext instantsi loomise koormust, kuid selles on peidetud väike auk. Hiljuti jooksis ASP.NET Core projekt järjest mõnda aega ja seejärel ilmus logides viga, et andmebaasi ühenduste bassein jõudis maksimaalse ühenduste arvuni:
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. aadressil System.Data.Common.ADP.ExceptionWithStackTrace(Exception e) Alguses arvasin, et see on mingi kood, mis põhjustab DbContexti korrektse kõrvaldamise, kuid ma ei leidnud koodist ühtegi vihjet. Hiljem polnud enam midagi kahtlust, ainult DbContextPool, nii et proovisin DbContextPooli eemaldada, kuid viga kadus. Selle põhjustas tõepoolest DbContextPool, kuid mis paneb inimesi mõtlema, on see, et DbContextPool on algselt mõeldud selleks, et säästa DbContexti instantside loomise koormust, nii et kuidas see saab tarbida rohkem andmebaasiühendusi ja selle projekti koormus on väga väike, kuidas see saab kogu ühenduse basseini tarbida? Rääkisin sellest kummalisest probleemist täna nädalakoosolekul ja siis mõtlesin järsku, et iga DbContext instants hõivab andmebaasi ühenduse (SqlConnection) ning kui DbContextPool pole lubatud, siis kohe pärast päringu lõppu kõrvaldatakse vastav DbContext instants ja andmebaasi ühendus pannakse tagasi ühenduse basseini. DbContextPooli kasutades ei kõrvaldata DbContexti, vaid pannakse tagasi DbContextPooli pärast päringu lõppu ning DbContext pannakse tagasi omaette basseini, mis tähendab, et vastavat andmebaasiühendust ei tagastata selle kuuluvasse ühendusgruppi. Iga DbContextPool DbContextPoolis vastab andmebaasi ühendusele ning iga täiendava DbContexti puhul on andmebaasi ühenduste basseinis üks ühendus vähem. Kui kaks basseini suurust on erineva suurusega ja DbContextPool on suurem kui andmebaasi ühenduse bassein, tekib probleem – DbContextPool täidab DbContexti vabalt basseini vastavalt omaenda basseini suurusele (oletame, et see on 128), ignoreerides andmebaasi ühenduse basseini suurust (eeldades, et see on 100), ning ülaltoodud viga tekib siis, kui 101. DbContext on täidetud. See projekt kasutab vaikimisi seadeid, kas vaikimisi seaded tekitavad selle probleemi?
Vaadates DbContextPooli rakenduse lähtekoodi, on avastamise basseini vaikimisi suurusepiirang 128
Vaadates SqlConnentioni rakenduse lähtekoodi, leiad, et vaikimisi ühenduse basseinide suurusepiirang on 100
Vaikeseade käivitab probleemi, mis on tegelikult väike lõks.
Teades põhjust, on lahendus lihtne: sea DbContextPooli poolSize väiksemaks kui andmebaasi ühenduse basseini Max_Pool_Size
|