[{"data":1,"prerenderedAt":3131},["ShallowReactive",2],{"article-it-mvcc-transactions-in-blite":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"tags":11,"body":20,"_type":3124,"_id":3125,"_source":3126,"_file":3127,"_stem":3128,"_extension":3129,"sitemap":3130},"\u002Fit\u002Fblog\u002Fmvcc-transactions-in-blite","blog",false,"","MVCC Lite: Come BLite Ti Dà le Transazioni Senza un Engine di Concorrenza Completo","Come BLite implementa l'isolamento delle transazioni usando due dizionari in memoria — un WAL cache per le scritture uncommitted e un WAL index per le pagine committed-ma-non-ancora-checkpointed — e dove questo approccio si discosta dal vero MVCC.","2026-03-31",[12,13,14,15,16,17,18,19],".net","blite","mvcc","transactions","concurrency","acid","open-source","internals",{"type":21,"children":22,"toc":3112},"root",[23,31,36,40,47,60,65,70,73,79,84,258,282,299,304,660,679,682,688,699,864,874,1178,1203,1520,1537,1630,1635,1638,1656,1661,2311,2323,2326,2340,2352,2524,2549,2552,2558,2577,2924,2943,2946,2952,2957,3009,3014,3031,3055,3072,3075,3081,3086,3091,3106],{"type":24,"tag":25,"props":26,"children":27},"element","p",{},[28],{"type":29,"value":30},"text","Ogni database serio fa la stessa promessa: una transazione o viene completata interamente oppure non avviene affatto. Leggere dati a metà transazione ti dà uno snapshot coerente, non un miscuglio di dati scritti a metà. E se il processo crasha, non perdi i dati committed.",{"type":24,"tag":25,"props":32,"children":33},{},[34],{"type":29,"value":35},"Mantenere quelle promesse mentre si consentono lettori e scrittori concorrenti è la parte difficile. La maggior parte dei database in produzione usa il Multi-Version Concurrency Control — MVCC — per farlo. BLite usa un modello più semplice che ottiene la maggior parte delle garanzie con una frazione della complessità. Ecco esattamente come funziona e dove sono le crepe.",{"type":24,"tag":37,"props":38,"children":39},"hr",{},[],{"type":24,"tag":41,"props":42,"children":44},"h2",{"id":43},"il-problema-che-mvcc-risolve",[45],{"type":29,"value":46},"Il Problema che MVCC Risolve",{"type":24,"tag":25,"props":48,"children":49},{},[50,52,58],{"type":29,"value":51},"Senza nessun controllo della concorrenza, due transazioni che leggono e scrivono le stesse pagine simultaneamente producono il caos: una transazione legge una pagina che un'altra sta scrivendo a metà. La soluzione è dare a ogni transazione la propria ",{"type":24,"tag":53,"props":54,"children":55},"em",{},[56],{"type":29,"value":57},"vista",{"type":29,"value":59}," dei dati — uno snapshot preso al momento in cui la transazione è iniziata, immune a modifiche concorrenti.",{"type":24,"tag":25,"props":61,"children":62},{},[63],{"type":29,"value":64},"Il vero MVCC (come in PostgreSQL) lo fa con catene di versioni: ogni riga aggiornata mantiene la sua vecchia versione su disco accanto a quella nuova, etichettata con gli ID delle transazioni. I lettori scelgono la versione il cui timestamp è ≤ al loro tempo di inizio transazione. Gli scrittori non bloccano mai i lettori.",{"type":24,"tag":25,"props":66,"children":67},{},[68],{"type":29,"value":69},"Questo è potente e generale. È anche complesso: processi di vacuum, tuple header, wraparound degli ID di transazione, visibility map. BLite adotta un approccio diverso.",{"type":24,"tag":37,"props":71,"children":72},{},[],{"type":24,"tag":41,"props":74,"children":76},{"id":75},"due-dizionari-un-contratto",[77],{"type":29,"value":78},"Due Dizionari, Un Contratto",{"type":24,"tag":25,"props":80,"children":81},{},[82],{"type":29,"value":83},"L'isolamento delle transazioni in BLite è costruito su due strutture dati in memoria:",{"type":24,"tag":85,"props":86,"children":90},"pre",{"className":87,"code":88,"language":89,"meta":7,"style":7},"language-csharp shiki shiki-themes one-dark-pro","\u002F\u002F Scritture uncommitted per transazione\nprivate readonly ConcurrentDictionary\u003Culong, ConcurrentDictionary\u003Cuint, byte[]>> _walCache = new();\n\n\u002F\u002F Pagine committed-ma-non-ancora-checkpointed (il \"ring stabile\")\nprivate readonly ConcurrentDictionary\u003Cuint, byte[]> _walIndex = new();\n","csharp",[91],{"type":24,"tag":92,"props":93,"children":94},"code",{"__ignoreMap":7},[95,107,189,199,208],{"type":24,"tag":96,"props":97,"children":100},"span",{"class":98,"line":99},"line",1,[101],{"type":24,"tag":96,"props":102,"children":104},{"style":103},"--shiki-default:#7F848E;--shiki-default-font-style:italic",[105],{"type":29,"value":106},"\u002F\u002F Scritture uncommitted per transazione\n",{"type":24,"tag":96,"props":108,"children":110},{"class":98,"line":109},2,[111,117,122,128,134,139,144,149,153,158,162,167,172,178,184],{"type":24,"tag":96,"props":112,"children":114},{"style":113},"--shiki-default:#C678DD",[115],{"type":29,"value":116},"private",{"type":24,"tag":96,"props":118,"children":119},{"style":113},[120],{"type":29,"value":121}," readonly",{"type":24,"tag":96,"props":123,"children":125},{"style":124},"--shiki-default:#E5C07B",[126],{"type":29,"value":127}," ConcurrentDictionary",{"type":24,"tag":96,"props":129,"children":131},{"style":130},"--shiki-default:#ABB2BF",[132],{"type":29,"value":133},"\u003C",{"type":24,"tag":96,"props":135,"children":136},{"style":113},[137],{"type":29,"value":138},"ulong",{"type":24,"tag":96,"props":140,"children":141},{"style":130},[142],{"type":29,"value":143},", ",{"type":24,"tag":96,"props":145,"children":146},{"style":124},[147],{"type":29,"value":148},"ConcurrentDictionary",{"type":24,"tag":96,"props":150,"children":151},{"style":130},[152],{"type":29,"value":133},{"type":24,"tag":96,"props":154,"children":155},{"style":113},[156],{"type":29,"value":157},"uint",{"type":24,"tag":96,"props":159,"children":160},{"style":130},[161],{"type":29,"value":143},{"type":24,"tag":96,"props":163,"children":164},{"style":113},[165],{"type":29,"value":166},"byte",{"type":24,"tag":96,"props":168,"children":169},{"style":130},[170],{"type":29,"value":171},"[]>> ",{"type":24,"tag":96,"props":173,"children":175},{"style":174},"--shiki-default:#E06C75",[176],{"type":29,"value":177},"_walCache",{"type":24,"tag":96,"props":179,"children":181},{"style":180},"--shiki-default:#56B6C2",[182],{"type":29,"value":183}," =",{"type":24,"tag":96,"props":185,"children":186},{"style":130},[187],{"type":29,"value":188}," new();\n",{"type":24,"tag":96,"props":190,"children":192},{"class":98,"line":191},3,[193],{"type":24,"tag":96,"props":194,"children":196},{"emptyLinePlaceholder":195},true,[197],{"type":29,"value":198},"\n",{"type":24,"tag":96,"props":200,"children":202},{"class":98,"line":201},4,[203],{"type":24,"tag":96,"props":204,"children":205},{"style":103},[206],{"type":29,"value":207},"\u002F\u002F Pagine committed-ma-non-ancora-checkpointed (il \"ring stabile\")\n",{"type":24,"tag":96,"props":209,"children":211},{"class":98,"line":210},5,[212,216,220,224,228,232,236,240,245,250,254],{"type":24,"tag":96,"props":213,"children":214},{"style":113},[215],{"type":29,"value":116},{"type":24,"tag":96,"props":217,"children":218},{"style":113},[219],{"type":29,"value":121},{"type":24,"tag":96,"props":221,"children":222},{"style":124},[223],{"type":29,"value":127},{"type":24,"tag":96,"props":225,"children":226},{"style":130},[227],{"type":29,"value":133},{"type":24,"tag":96,"props":229,"children":230},{"style":113},[231],{"type":29,"value":157},{"type":24,"tag":96,"props":233,"children":234},{"style":130},[235],{"type":29,"value":143},{"type":24,"tag":96,"props":237,"children":238},{"style":113},[239],{"type":29,"value":166},{"type":24,"tag":96,"props":241,"children":242},{"style":130},[243],{"type":29,"value":244},"[]> ",{"type":24,"tag":96,"props":246,"children":247},{"style":174},[248],{"type":29,"value":249},"_walIndex",{"type":24,"tag":96,"props":251,"children":252},{"style":180},[253],{"type":29,"value":183},{"type":24,"tag":96,"props":255,"children":256},{"style":130},[257],{"type":29,"value":188},{"type":24,"tag":25,"props":259,"children":260},{},[261,266,268,273,275,280],{"type":24,"tag":92,"props":262,"children":264},{"className":263},[],[265],{"type":29,"value":177},{"type":29,"value":267}," è un dizionario di dizionari: la chiave esterna è l'ID della transazione (",{"type":24,"tag":92,"props":269,"children":271},{"className":270},[],[272],{"type":29,"value":138},{"type":29,"value":274},"), la chiave interna è il page ID (",{"type":24,"tag":92,"props":276,"children":278},{"className":277},[],[279],{"type":29,"value":157},{"type":29,"value":281},"), e il valore è l'array di byte della pagina. Ogni scrittura va nella cache privata del chiamante, invisibile agli altri.",{"type":24,"tag":25,"props":283,"children":284},{},[285,290,292,297],{"type":24,"tag":92,"props":286,"children":288},{"className":287},[],[289],{"type":29,"value":249},{"type":29,"value":291}," è un dizionario piatto: page ID → byte array corrente. Rappresenta lo stato committed di tutte le pagine scritte dall'ultimo checkpoint. Quando si legge una pagina, si controlla prima ",{"type":24,"tag":92,"props":293,"children":295},{"className":294},[],[296],{"type":29,"value":249},{"type":29,"value":298}," per la versione committed.",{"type":24,"tag":25,"props":300,"children":301},{},[302],{"type":29,"value":303},"Il percorso di lettura combina entrambi:",{"type":24,"tag":85,"props":305,"children":307},{"className":87,"code":306,"language":89,"meta":7,"style":7},"public byte[] ReadPage(uint pageId, ulong transactionId)\n{\n    \u002F\u002F Prima: verifica se questa transazione ha scritto la pagina (leggi le tue scritture)\n    if (_walCache.TryGetValue(transactionId, out var txnCache) &&\n        txnCache.TryGetValue(pageId, out var uncommitted))\n        return uncommitted;\n\n    \u002F\u002F Seconda: verifica se esiste una versione committed dall'ultimo checkpoint\n    if (_walIndex.TryGetValue(pageId, out var committed))\n        return committed;\n\n    \u002F\u002F Terza: leggi dal file di pagine durabilmente persistito\n    return _pageFile.ReadPage(pageId);\n}\n",[308],{"type":24,"tag":92,"props":309,"children":310},{"__ignoreMap":7},[311,367,375,383,448,495,513,521,530,583,599,607,616,651],{"type":24,"tag":96,"props":312,"children":313},{"class":98,"line":99},[314,319,324,329,335,340,344,349,353,357,362],{"type":24,"tag":96,"props":315,"children":316},{"style":113},[317],{"type":29,"value":318},"public",{"type":24,"tag":96,"props":320,"children":321},{"style":113},[322],{"type":29,"value":323}," byte",{"type":24,"tag":96,"props":325,"children":326},{"style":130},[327],{"type":29,"value":328},"[] ",{"type":24,"tag":96,"props":330,"children":332},{"style":331},"--shiki-default:#61AFEF",[333],{"type":29,"value":334},"ReadPage",{"type":24,"tag":96,"props":336,"children":337},{"style":130},[338],{"type":29,"value":339},"(",{"type":24,"tag":96,"props":341,"children":342},{"style":113},[343],{"type":29,"value":157},{"type":24,"tag":96,"props":345,"children":346},{"style":124},[347],{"type":29,"value":348}," pageId",{"type":24,"tag":96,"props":350,"children":351},{"style":130},[352],{"type":29,"value":143},{"type":24,"tag":96,"props":354,"children":355},{"style":113},[356],{"type":29,"value":138},{"type":24,"tag":96,"props":358,"children":359},{"style":124},[360],{"type":29,"value":361}," transactionId",{"type":24,"tag":96,"props":363,"children":364},{"style":130},[365],{"type":29,"value":366},")\n",{"type":24,"tag":96,"props":368,"children":369},{"class":98,"line":109},[370],{"type":24,"tag":96,"props":371,"children":372},{"style":130},[373],{"type":29,"value":374},"{\n",{"type":24,"tag":96,"props":376,"children":377},{"class":98,"line":191},[378],{"type":24,"tag":96,"props":379,"children":380},{"style":103},[381],{"type":29,"value":382},"    \u002F\u002F Prima: verifica se questa transazione ha scritto la pagina (leggi le tue scritture)\n",{"type":24,"tag":96,"props":384,"children":385},{"class":98,"line":201},[386,391,396,400,405,410,414,419,423,428,433,438,443],{"type":24,"tag":96,"props":387,"children":388},{"style":113},[389],{"type":29,"value":390},"    if",{"type":24,"tag":96,"props":392,"children":393},{"style":130},[394],{"type":29,"value":395}," (",{"type":24,"tag":96,"props":397,"children":398},{"style":124},[399],{"type":29,"value":177},{"type":24,"tag":96,"props":401,"children":402},{"style":130},[403],{"type":29,"value":404},".",{"type":24,"tag":96,"props":406,"children":407},{"style":331},[408],{"type":29,"value":409},"TryGetValue",{"type":24,"tag":96,"props":411,"children":412},{"style":130},[413],{"type":29,"value":339},{"type":24,"tag":96,"props":415,"children":416},{"style":174},[417],{"type":29,"value":418},"transactionId",{"type":24,"tag":96,"props":420,"children":421},{"style":130},[422],{"type":29,"value":143},{"type":24,"tag":96,"props":424,"children":425},{"style":113},[426],{"type":29,"value":427},"out",{"type":24,"tag":96,"props":429,"children":430},{"style":113},[431],{"type":29,"value":432}," var",{"type":24,"tag":96,"props":434,"children":435},{"style":174},[436],{"type":29,"value":437}," txnCache",{"type":24,"tag":96,"props":439,"children":440},{"style":130},[441],{"type":29,"value":442},") ",{"type":24,"tag":96,"props":444,"children":445},{"style":180},[446],{"type":29,"value":447},"&&\n",{"type":24,"tag":96,"props":449,"children":450},{"class":98,"line":210},[451,456,460,464,468,473,477,481,485,490],{"type":24,"tag":96,"props":452,"children":453},{"style":124},[454],{"type":29,"value":455},"        txnCache",{"type":24,"tag":96,"props":457,"children":458},{"style":130},[459],{"type":29,"value":404},{"type":24,"tag":96,"props":461,"children":462},{"style":331},[463],{"type":29,"value":409},{"type":24,"tag":96,"props":465,"children":466},{"style":130},[467],{"type":29,"value":339},{"type":24,"tag":96,"props":469,"children":470},{"style":174},[471],{"type":29,"value":472},"pageId",{"type":24,"tag":96,"props":474,"children":475},{"style":130},[476],{"type":29,"value":143},{"type":24,"tag":96,"props":478,"children":479},{"style":113},[480],{"type":29,"value":427},{"type":24,"tag":96,"props":482,"children":483},{"style":113},[484],{"type":29,"value":432},{"type":24,"tag":96,"props":486,"children":487},{"style":174},[488],{"type":29,"value":489}," uncommitted",{"type":24,"tag":96,"props":491,"children":492},{"style":130},[493],{"type":29,"value":494},"))\n",{"type":24,"tag":96,"props":496,"children":498},{"class":98,"line":497},6,[499,504,508],{"type":24,"tag":96,"props":500,"children":501},{"style":113},[502],{"type":29,"value":503},"        return",{"type":24,"tag":96,"props":505,"children":506},{"style":174},[507],{"type":29,"value":489},{"type":24,"tag":96,"props":509,"children":510},{"style":130},[511],{"type":29,"value":512},";\n",{"type":24,"tag":96,"props":514,"children":516},{"class":98,"line":515},7,[517],{"type":24,"tag":96,"props":518,"children":519},{"emptyLinePlaceholder":195},[520],{"type":29,"value":198},{"type":24,"tag":96,"props":522,"children":524},{"class":98,"line":523},8,[525],{"type":24,"tag":96,"props":526,"children":527},{"style":103},[528],{"type":29,"value":529},"    \u002F\u002F Seconda: verifica se esiste una versione committed dall'ultimo checkpoint\n",{"type":24,"tag":96,"props":531,"children":533},{"class":98,"line":532},9,[534,538,542,546,550,554,558,562,566,570,574,579],{"type":24,"tag":96,"props":535,"children":536},{"style":113},[537],{"type":29,"value":390},{"type":24,"tag":96,"props":539,"children":540},{"style":130},[541],{"type":29,"value":395},{"type":24,"tag":96,"props":543,"children":544},{"style":124},[545],{"type":29,"value":249},{"type":24,"tag":96,"props":547,"children":548},{"style":130},[549],{"type":29,"value":404},{"type":24,"tag":96,"props":551,"children":552},{"style":331},[553],{"type":29,"value":409},{"type":24,"tag":96,"props":555,"children":556},{"style":130},[557],{"type":29,"value":339},{"type":24,"tag":96,"props":559,"children":560},{"style":174},[561],{"type":29,"value":472},{"type":24,"tag":96,"props":563,"children":564},{"style":130},[565],{"type":29,"value":143},{"type":24,"tag":96,"props":567,"children":568},{"style":113},[569],{"type":29,"value":427},{"type":24,"tag":96,"props":571,"children":572},{"style":113},[573],{"type":29,"value":432},{"type":24,"tag":96,"props":575,"children":576},{"style":174},[577],{"type":29,"value":578}," committed",{"type":24,"tag":96,"props":580,"children":581},{"style":130},[582],{"type":29,"value":494},{"type":24,"tag":96,"props":584,"children":586},{"class":98,"line":585},10,[587,591,595],{"type":24,"tag":96,"props":588,"children":589},{"style":113},[590],{"type":29,"value":503},{"type":24,"tag":96,"props":592,"children":593},{"style":174},[594],{"type":29,"value":578},{"type":24,"tag":96,"props":596,"children":597},{"style":130},[598],{"type":29,"value":512},{"type":24,"tag":96,"props":600,"children":602},{"class":98,"line":601},11,[603],{"type":24,"tag":96,"props":604,"children":605},{"emptyLinePlaceholder":195},[606],{"type":29,"value":198},{"type":24,"tag":96,"props":608,"children":610},{"class":98,"line":609},12,[611],{"type":24,"tag":96,"props":612,"children":613},{"style":103},[614],{"type":29,"value":615},"    \u002F\u002F Terza: leggi dal file di pagine durabilmente persistito\n",{"type":24,"tag":96,"props":617,"children":619},{"class":98,"line":618},13,[620,625,630,634,638,642,646],{"type":24,"tag":96,"props":621,"children":622},{"style":113},[623],{"type":29,"value":624},"    return",{"type":24,"tag":96,"props":626,"children":627},{"style":124},[628],{"type":29,"value":629}," _pageFile",{"type":24,"tag":96,"props":631,"children":632},{"style":130},[633],{"type":29,"value":404},{"type":24,"tag":96,"props":635,"children":636},{"style":331},[637],{"type":29,"value":334},{"type":24,"tag":96,"props":639,"children":640},{"style":130},[641],{"type":29,"value":339},{"type":24,"tag":96,"props":643,"children":644},{"style":174},[645],{"type":29,"value":472},{"type":24,"tag":96,"props":647,"children":648},{"style":130},[649],{"type":29,"value":650},");\n",{"type":24,"tag":96,"props":652,"children":654},{"class":98,"line":653},14,[655],{"type":24,"tag":96,"props":656,"children":657},{"style":130},[658],{"type":29,"value":659},"}\n",{"type":24,"tag":25,"props":661,"children":662},{},[663,665,670,672,677],{"type":29,"value":664},"Una transazione legge sempre le proprie scritture uncommitted. Se non ha toccato una pagina, legge da ",{"type":24,"tag":92,"props":666,"children":668},{"className":667},[],[669],{"type":29,"value":249},{"type":29,"value":671}," — lo stato committed delle transazioni precedenti (committed). Se ",{"type":24,"tag":92,"props":673,"children":675},{"className":674},[],[676],{"type":29,"value":249},{"type":29,"value":678}," non ha nemmeno la pagina, cade sul file di pagine durevole.",{"type":24,"tag":37,"props":680,"children":681},{},[],{"type":24,"tag":41,"props":683,"children":685},{"id":684},"ciclo-di-vita-di-una-transazione",[686],{"type":29,"value":687},"Ciclo di Vita di una Transazione",{"type":24,"tag":25,"props":689,"children":690},{},[691,697],{"type":24,"tag":692,"props":693,"children":694},"strong",{},[695],{"type":29,"value":696},"Begin:",{"type":29,"value":698}," Alloca semplicemente un nuovo ID di transazione. Nient'altro ancora.",{"type":24,"tag":85,"props":700,"children":702},{"className":87,"code":701,"language":89,"meta":7,"style":7},"public ulong BeginTransaction()\n{\n    ulong txnId = Interlocked.Increment(ref _transactionCounter);\n    _walCache[txnId] = new ConcurrentDictionary\u003Cuint, byte[]>();\n    return txnId;\n}\n",[703],{"type":24,"tag":92,"props":704,"children":705},{"__ignoreMap":7},[706,728,735,784,842,857],{"type":24,"tag":96,"props":707,"children":708},{"class":98,"line":99},[709,713,718,723],{"type":24,"tag":96,"props":710,"children":711},{"style":113},[712],{"type":29,"value":318},{"type":24,"tag":96,"props":714,"children":715},{"style":113},[716],{"type":29,"value":717}," ulong",{"type":24,"tag":96,"props":719,"children":720},{"style":331},[721],{"type":29,"value":722}," BeginTransaction",{"type":24,"tag":96,"props":724,"children":725},{"style":130},[726],{"type":29,"value":727},"()\n",{"type":24,"tag":96,"props":729,"children":730},{"class":98,"line":109},[731],{"type":24,"tag":96,"props":732,"children":733},{"style":130},[734],{"type":29,"value":374},{"type":24,"tag":96,"props":736,"children":737},{"class":98,"line":191},[738,743,748,752,757,761,766,770,775,780],{"type":24,"tag":96,"props":739,"children":740},{"style":113},[741],{"type":29,"value":742},"    ulong",{"type":24,"tag":96,"props":744,"children":745},{"style":174},[746],{"type":29,"value":747}," txnId",{"type":24,"tag":96,"props":749,"children":750},{"style":180},[751],{"type":29,"value":183},{"type":24,"tag":96,"props":753,"children":754},{"style":124},[755],{"type":29,"value":756}," Interlocked",{"type":24,"tag":96,"props":758,"children":759},{"style":130},[760],{"type":29,"value":404},{"type":24,"tag":96,"props":762,"children":763},{"style":331},[764],{"type":29,"value":765},"Increment",{"type":24,"tag":96,"props":767,"children":768},{"style":130},[769],{"type":29,"value":339},{"type":24,"tag":96,"props":771,"children":772},{"style":113},[773],{"type":29,"value":774},"ref",{"type":24,"tag":96,"props":776,"children":777},{"style":174},[778],{"type":29,"value":779}," _transactionCounter",{"type":24,"tag":96,"props":781,"children":782},{"style":130},[783],{"type":29,"value":650},{"type":24,"tag":96,"props":785,"children":786},{"class":98,"line":201},[787,792,797,802,807,812,817,821,825,829,833,837],{"type":24,"tag":96,"props":788,"children":789},{"style":124},[790],{"type":29,"value":791},"    _walCache",{"type":24,"tag":96,"props":793,"children":794},{"style":130},[795],{"type":29,"value":796},"[",{"type":24,"tag":96,"props":798,"children":799},{"style":174},[800],{"type":29,"value":801},"txnId",{"type":24,"tag":96,"props":803,"children":804},{"style":130},[805],{"type":29,"value":806},"] ",{"type":24,"tag":96,"props":808,"children":809},{"style":180},[810],{"type":29,"value":811},"=",{"type":24,"tag":96,"props":813,"children":814},{"style":130},[815],{"type":29,"value":816}," new ",{"type":24,"tag":96,"props":818,"children":819},{"style":124},[820],{"type":29,"value":148},{"type":24,"tag":96,"props":822,"children":823},{"style":130},[824],{"type":29,"value":133},{"type":24,"tag":96,"props":826,"children":827},{"style":113},[828],{"type":29,"value":157},{"type":24,"tag":96,"props":830,"children":831},{"style":130},[832],{"type":29,"value":143},{"type":24,"tag":96,"props":834,"children":835},{"style":113},[836],{"type":29,"value":166},{"type":24,"tag":96,"props":838,"children":839},{"style":130},[840],{"type":29,"value":841},"[]>();\n",{"type":24,"tag":96,"props":843,"children":844},{"class":98,"line":210},[845,849,853],{"type":24,"tag":96,"props":846,"children":847},{"style":113},[848],{"type":29,"value":624},{"type":24,"tag":96,"props":850,"children":851},{"style":174},[852],{"type":29,"value":747},{"type":24,"tag":96,"props":854,"children":855},{"style":130},[856],{"type":29,"value":512},{"type":24,"tag":96,"props":858,"children":859},{"class":98,"line":497},[860],{"type":24,"tag":96,"props":861,"children":862},{"style":130},[863],{"type":29,"value":659},{"type":24,"tag":25,"props":865,"children":866},{},[867,872],{"type":24,"tag":692,"props":868,"children":869},{},[870],{"type":29,"value":871},"Write:",{"type":29,"value":873}," Bufferizza la pagina modificata nella cache privata della transazione.",{"type":24,"tag":85,"props":875,"children":877},{"className":87,"code":876,"language":89,"meta":7,"style":7},"public void WritePage(uint pageId, byte[] data, ulong transactionId)\n{\n    if (!_walCache.TryGetValue(transactionId, out var txnCache))\n        throw new InvalidOperationException(\"Nessuna transazione attiva\");\n\n    \u002F\u002F Copia per permettere al chiamante di riutilizzare il suo buffer\n    var copy = new byte[data.Length];\n    data.CopyTo(copy, 0);\n    txnCache[pageId] = copy;\n}\n",[878],{"type":24,"tag":92,"props":879,"children":880},{"__ignoreMap":7},[881,943,950,1006,1037,1044,1052,1099,1139,1171],{"type":24,"tag":96,"props":882,"children":883},{"class":98,"line":99},[884,888,893,898,902,906,910,914,918,922,927,931,935,939],{"type":24,"tag":96,"props":885,"children":886},{"style":113},[887],{"type":29,"value":318},{"type":24,"tag":96,"props":889,"children":890},{"style":113},[891],{"type":29,"value":892}," void",{"type":24,"tag":96,"props":894,"children":895},{"style":331},[896],{"type":29,"value":897}," WritePage",{"type":24,"tag":96,"props":899,"children":900},{"style":130},[901],{"type":29,"value":339},{"type":24,"tag":96,"props":903,"children":904},{"style":113},[905],{"type":29,"value":157},{"type":24,"tag":96,"props":907,"children":908},{"style":124},[909],{"type":29,"value":348},{"type":24,"tag":96,"props":911,"children":912},{"style":130},[913],{"type":29,"value":143},{"type":24,"tag":96,"props":915,"children":916},{"style":113},[917],{"type":29,"value":166},{"type":24,"tag":96,"props":919,"children":920},{"style":130},[921],{"type":29,"value":328},{"type":24,"tag":96,"props":923,"children":924},{"style":124},[925],{"type":29,"value":926},"data",{"type":24,"tag":96,"props":928,"children":929},{"style":130},[930],{"type":29,"value":143},{"type":24,"tag":96,"props":932,"children":933},{"style":113},[934],{"type":29,"value":138},{"type":24,"tag":96,"props":936,"children":937},{"style":124},[938],{"type":29,"value":361},{"type":24,"tag":96,"props":940,"children":941},{"style":130},[942],{"type":29,"value":366},{"type":24,"tag":96,"props":944,"children":945},{"class":98,"line":109},[946],{"type":24,"tag":96,"props":947,"children":948},{"style":130},[949],{"type":29,"value":374},{"type":24,"tag":96,"props":951,"children":952},{"class":98,"line":191},[953,957,961,966,970,974,978,982,986,990,994,998,1002],{"type":24,"tag":96,"props":954,"children":955},{"style":113},[956],{"type":29,"value":390},{"type":24,"tag":96,"props":958,"children":959},{"style":130},[960],{"type":29,"value":395},{"type":24,"tag":96,"props":962,"children":963},{"style":180},[964],{"type":29,"value":965},"!",{"type":24,"tag":96,"props":967,"children":968},{"style":124},[969],{"type":29,"value":177},{"type":24,"tag":96,"props":971,"children":972},{"style":130},[973],{"type":29,"value":404},{"type":24,"tag":96,"props":975,"children":976},{"style":331},[977],{"type":29,"value":409},{"type":24,"tag":96,"props":979,"children":980},{"style":130},[981],{"type":29,"value":339},{"type":24,"tag":96,"props":983,"children":984},{"style":174},[985],{"type":29,"value":418},{"type":24,"tag":96,"props":987,"children":988},{"style":130},[989],{"type":29,"value":143},{"type":24,"tag":96,"props":991,"children":992},{"style":113},[993],{"type":29,"value":427},{"type":24,"tag":96,"props":995,"children":996},{"style":113},[997],{"type":29,"value":432},{"type":24,"tag":96,"props":999,"children":1000},{"style":174},[1001],{"type":29,"value":437},{"type":24,"tag":96,"props":1003,"children":1004},{"style":130},[1005],{"type":29,"value":494},{"type":24,"tag":96,"props":1007,"children":1008},{"class":98,"line":201},[1009,1014,1018,1023,1027,1033],{"type":24,"tag":96,"props":1010,"children":1011},{"style":113},[1012],{"type":29,"value":1013},"        throw",{"type":24,"tag":96,"props":1015,"children":1016},{"style":130},[1017],{"type":29,"value":816},{"type":24,"tag":96,"props":1019,"children":1020},{"style":124},[1021],{"type":29,"value":1022},"InvalidOperationException",{"type":24,"tag":96,"props":1024,"children":1025},{"style":130},[1026],{"type":29,"value":339},{"type":24,"tag":96,"props":1028,"children":1030},{"style":1029},"--shiki-default:#98C379",[1031],{"type":29,"value":1032},"\"Nessuna transazione attiva\"",{"type":24,"tag":96,"props":1034,"children":1035},{"style":130},[1036],{"type":29,"value":650},{"type":24,"tag":96,"props":1038,"children":1039},{"class":98,"line":210},[1040],{"type":24,"tag":96,"props":1041,"children":1042},{"emptyLinePlaceholder":195},[1043],{"type":29,"value":198},{"type":24,"tag":96,"props":1045,"children":1046},{"class":98,"line":497},[1047],{"type":24,"tag":96,"props":1048,"children":1049},{"style":103},[1050],{"type":29,"value":1051},"    \u002F\u002F Copia per permettere al chiamante di riutilizzare il suo buffer\n",{"type":24,"tag":96,"props":1053,"children":1054},{"class":98,"line":515},[1055,1060,1065,1069,1073,1077,1081,1085,1089,1094],{"type":24,"tag":96,"props":1056,"children":1057},{"style":113},[1058],{"type":29,"value":1059},"    var",{"type":24,"tag":96,"props":1061,"children":1062},{"style":174},[1063],{"type":29,"value":1064}," copy",{"type":24,"tag":96,"props":1066,"children":1067},{"style":180},[1068],{"type":29,"value":183},{"type":24,"tag":96,"props":1070,"children":1071},{"style":130},[1072],{"type":29,"value":816},{"type":24,"tag":96,"props":1074,"children":1075},{"style":113},[1076],{"type":29,"value":166},{"type":24,"tag":96,"props":1078,"children":1079},{"style":130},[1080],{"type":29,"value":796},{"type":24,"tag":96,"props":1082,"children":1083},{"style":124},[1084],{"type":29,"value":926},{"type":24,"tag":96,"props":1086,"children":1087},{"style":130},[1088],{"type":29,"value":404},{"type":24,"tag":96,"props":1090,"children":1091},{"style":124},[1092],{"type":29,"value":1093},"Length",{"type":24,"tag":96,"props":1095,"children":1096},{"style":130},[1097],{"type":29,"value":1098},"];\n",{"type":24,"tag":96,"props":1100,"children":1101},{"class":98,"line":523},[1102,1107,1111,1116,1120,1125,1129,1135],{"type":24,"tag":96,"props":1103,"children":1104},{"style":124},[1105],{"type":29,"value":1106},"    data",{"type":24,"tag":96,"props":1108,"children":1109},{"style":130},[1110],{"type":29,"value":404},{"type":24,"tag":96,"props":1112,"children":1113},{"style":331},[1114],{"type":29,"value":1115},"CopyTo",{"type":24,"tag":96,"props":1117,"children":1118},{"style":130},[1119],{"type":29,"value":339},{"type":24,"tag":96,"props":1121,"children":1122},{"style":174},[1123],{"type":29,"value":1124},"copy",{"type":24,"tag":96,"props":1126,"children":1127},{"style":130},[1128],{"type":29,"value":143},{"type":24,"tag":96,"props":1130,"children":1132},{"style":1131},"--shiki-default:#D19A66",[1133],{"type":29,"value":1134},"0",{"type":24,"tag":96,"props":1136,"children":1137},{"style":130},[1138],{"type":29,"value":650},{"type":24,"tag":96,"props":1140,"children":1141},{"class":98,"line":532},[1142,1147,1151,1155,1159,1163,1167],{"type":24,"tag":96,"props":1143,"children":1144},{"style":124},[1145],{"type":29,"value":1146},"    txnCache",{"type":24,"tag":96,"props":1148,"children":1149},{"style":130},[1150],{"type":29,"value":796},{"type":24,"tag":96,"props":1152,"children":1153},{"style":174},[1154],{"type":29,"value":472},{"type":24,"tag":96,"props":1156,"children":1157},{"style":130},[1158],{"type":29,"value":806},{"type":24,"tag":96,"props":1160,"children":1161},{"style":180},[1162],{"type":29,"value":811},{"type":24,"tag":96,"props":1164,"children":1165},{"style":174},[1166],{"type":29,"value":1064},{"type":24,"tag":96,"props":1168,"children":1169},{"style":130},[1170],{"type":29,"value":512},{"type":24,"tag":96,"props":1172,"children":1173},{"class":98,"line":585},[1174],{"type":24,"tag":96,"props":1175,"children":1176},{"style":130},[1177],{"type":29,"value":659},{"type":24,"tag":25,"props":1179,"children":1180},{},[1181,1186,1188,1193,1195,1201],{"type":24,"tag":692,"props":1182,"children":1183},{},[1184],{"type":29,"value":1185},"Commit:",{"type":29,"value":1187}," Consegna le pagine dirty della transazione alla pipeline del group commit, che le raggruppa nel WAL, le flushta su disco, le sposta in ",{"type":24,"tag":92,"props":1189,"children":1191},{"className":1190},[],[1192],{"type":29,"value":249},{"type":29,"value":1194}," e completa il ",{"type":24,"tag":92,"props":1196,"children":1198},{"className":1197},[],[1199],{"type":29,"value":1200},"TaskCompletionSource",{"type":29,"value":1202}," che il chiamante sta aspettando.",{"type":24,"tag":85,"props":1204,"children":1206},{"className":87,"code":1205,"language":89,"meta":7,"style":7},"public async Task CommitTransactionAsync(ulong transactionId)\n{\n    if (!_walCache.TryRemove(transactionId, out var txnCache))\n        throw new InvalidOperationException(\"Nessuna transazione attiva\");\n\n    var pending = new PendingCommit(transactionId, txnCache, new TaskCompletionSource(\n        TaskCreationOptions.RunContinuationsAsynchronously));\n\n    await _commitChannel.Writer.WriteAsync(pending);\n    await pending.Completion.Task; \u002F\u002F Aspetta che il group commit finisca\n}\n",[1207],{"type":24,"tag":92,"props":1208,"children":1209},{"__ignoreMap":7},[1210,1248,1255,1311,1338,1345,1401,1423,1430,1474,1513],{"type":24,"tag":96,"props":1211,"children":1212},{"class":98,"line":99},[1213,1217,1222,1227,1232,1236,1240,1244],{"type":24,"tag":96,"props":1214,"children":1215},{"style":113},[1216],{"type":29,"value":318},{"type":24,"tag":96,"props":1218,"children":1219},{"style":113},[1220],{"type":29,"value":1221}," async",{"type":24,"tag":96,"props":1223,"children":1224},{"style":124},[1225],{"type":29,"value":1226}," Task",{"type":24,"tag":96,"props":1228,"children":1229},{"style":331},[1230],{"type":29,"value":1231}," CommitTransactionAsync",{"type":24,"tag":96,"props":1233,"children":1234},{"style":130},[1235],{"type":29,"value":339},{"type":24,"tag":96,"props":1237,"children":1238},{"style":113},[1239],{"type":29,"value":138},{"type":24,"tag":96,"props":1241,"children":1242},{"style":124},[1243],{"type":29,"value":361},{"type":24,"tag":96,"props":1245,"children":1246},{"style":130},[1247],{"type":29,"value":366},{"type":24,"tag":96,"props":1249,"children":1250},{"class":98,"line":109},[1251],{"type":24,"tag":96,"props":1252,"children":1253},{"style":130},[1254],{"type":29,"value":374},{"type":24,"tag":96,"props":1256,"children":1257},{"class":98,"line":191},[1258,1262,1266,1270,1274,1278,1283,1287,1291,1295,1299,1303,1307],{"type":24,"tag":96,"props":1259,"children":1260},{"style":113},[1261],{"type":29,"value":390},{"type":24,"tag":96,"props":1263,"children":1264},{"style":130},[1265],{"type":29,"value":395},{"type":24,"tag":96,"props":1267,"children":1268},{"style":180},[1269],{"type":29,"value":965},{"type":24,"tag":96,"props":1271,"children":1272},{"style":124},[1273],{"type":29,"value":177},{"type":24,"tag":96,"props":1275,"children":1276},{"style":130},[1277],{"type":29,"value":404},{"type":24,"tag":96,"props":1279,"children":1280},{"style":331},[1281],{"type":29,"value":1282},"TryRemove",{"type":24,"tag":96,"props":1284,"children":1285},{"style":130},[1286],{"type":29,"value":339},{"type":24,"tag":96,"props":1288,"children":1289},{"style":174},[1290],{"type":29,"value":418},{"type":24,"tag":96,"props":1292,"children":1293},{"style":130},[1294],{"type":29,"value":143},{"type":24,"tag":96,"props":1296,"children":1297},{"style":113},[1298],{"type":29,"value":427},{"type":24,"tag":96,"props":1300,"children":1301},{"style":113},[1302],{"type":29,"value":432},{"type":24,"tag":96,"props":1304,"children":1305},{"style":174},[1306],{"type":29,"value":437},{"type":24,"tag":96,"props":1308,"children":1309},{"style":130},[1310],{"type":29,"value":494},{"type":24,"tag":96,"props":1312,"children":1313},{"class":98,"line":201},[1314,1318,1322,1326,1330,1334],{"type":24,"tag":96,"props":1315,"children":1316},{"style":113},[1317],{"type":29,"value":1013},{"type":24,"tag":96,"props":1319,"children":1320},{"style":130},[1321],{"type":29,"value":816},{"type":24,"tag":96,"props":1323,"children":1324},{"style":124},[1325],{"type":29,"value":1022},{"type":24,"tag":96,"props":1327,"children":1328},{"style":130},[1329],{"type":29,"value":339},{"type":24,"tag":96,"props":1331,"children":1332},{"style":1029},[1333],{"type":29,"value":1032},{"type":24,"tag":96,"props":1335,"children":1336},{"style":130},[1337],{"type":29,"value":650},{"type":24,"tag":96,"props":1339,"children":1340},{"class":98,"line":210},[1341],{"type":24,"tag":96,"props":1342,"children":1343},{"emptyLinePlaceholder":195},[1344],{"type":29,"value":198},{"type":24,"tag":96,"props":1346,"children":1347},{"class":98,"line":497},[1348,1352,1357,1361,1365,1370,1374,1378,1382,1387,1392,1396],{"type":24,"tag":96,"props":1349,"children":1350},{"style":113},[1351],{"type":29,"value":1059},{"type":24,"tag":96,"props":1353,"children":1354},{"style":174},[1355],{"type":29,"value":1356}," pending",{"type":24,"tag":96,"props":1358,"children":1359},{"style":180},[1360],{"type":29,"value":183},{"type":24,"tag":96,"props":1362,"children":1363},{"style":130},[1364],{"type":29,"value":816},{"type":24,"tag":96,"props":1366,"children":1367},{"style":124},[1368],{"type":29,"value":1369},"PendingCommit",{"type":24,"tag":96,"props":1371,"children":1372},{"style":130},[1373],{"type":29,"value":339},{"type":24,"tag":96,"props":1375,"children":1376},{"style":174},[1377],{"type":29,"value":418},{"type":24,"tag":96,"props":1379,"children":1380},{"style":130},[1381],{"type":29,"value":143},{"type":24,"tag":96,"props":1383,"children":1384},{"style":174},[1385],{"type":29,"value":1386},"txnCache",{"type":24,"tag":96,"props":1388,"children":1389},{"style":130},[1390],{"type":29,"value":1391},", new ",{"type":24,"tag":96,"props":1393,"children":1394},{"style":124},[1395],{"type":29,"value":1200},{"type":24,"tag":96,"props":1397,"children":1398},{"style":130},[1399],{"type":29,"value":1400},"(\n",{"type":24,"tag":96,"props":1402,"children":1403},{"class":98,"line":515},[1404,1409,1413,1418],{"type":24,"tag":96,"props":1405,"children":1406},{"style":124},[1407],{"type":29,"value":1408},"        TaskCreationOptions",{"type":24,"tag":96,"props":1410,"children":1411},{"style":130},[1412],{"type":29,"value":404},{"type":24,"tag":96,"props":1414,"children":1415},{"style":124},[1416],{"type":29,"value":1417},"RunContinuationsAsynchronously",{"type":24,"tag":96,"props":1419,"children":1420},{"style":130},[1421],{"type":29,"value":1422},"));\n",{"type":24,"tag":96,"props":1424,"children":1425},{"class":98,"line":523},[1426],{"type":24,"tag":96,"props":1427,"children":1428},{"emptyLinePlaceholder":195},[1429],{"type":29,"value":198},{"type":24,"tag":96,"props":1431,"children":1432},{"class":98,"line":532},[1433,1438,1443,1447,1452,1456,1461,1465,1470],{"type":24,"tag":96,"props":1434,"children":1435},{"style":130},[1436],{"type":29,"value":1437},"    await ",{"type":24,"tag":96,"props":1439,"children":1440},{"style":124},[1441],{"type":29,"value":1442},"_commitChannel",{"type":24,"tag":96,"props":1444,"children":1445},{"style":130},[1446],{"type":29,"value":404},{"type":24,"tag":96,"props":1448,"children":1449},{"style":124},[1450],{"type":29,"value":1451},"Writer",{"type":24,"tag":96,"props":1453,"children":1454},{"style":130},[1455],{"type":29,"value":404},{"type":24,"tag":96,"props":1457,"children":1458},{"style":331},[1459],{"type":29,"value":1460},"WriteAsync",{"type":24,"tag":96,"props":1462,"children":1463},{"style":130},[1464],{"type":29,"value":339},{"type":24,"tag":96,"props":1466,"children":1467},{"style":174},[1468],{"type":29,"value":1469},"pending",{"type":24,"tag":96,"props":1471,"children":1472},{"style":130},[1473],{"type":29,"value":650},{"type":24,"tag":96,"props":1475,"children":1476},{"class":98,"line":585},[1477,1481,1485,1489,1494,1498,1503,1508],{"type":24,"tag":96,"props":1478,"children":1479},{"style":130},[1480],{"type":29,"value":1437},{"type":24,"tag":96,"props":1482,"children":1483},{"style":124},[1484],{"type":29,"value":1469},{"type":24,"tag":96,"props":1486,"children":1487},{"style":130},[1488],{"type":29,"value":404},{"type":24,"tag":96,"props":1490,"children":1491},{"style":124},[1492],{"type":29,"value":1493},"Completion",{"type":24,"tag":96,"props":1495,"children":1496},{"style":130},[1497],{"type":29,"value":404},{"type":24,"tag":96,"props":1499,"children":1500},{"style":124},[1501],{"type":29,"value":1502},"Task",{"type":24,"tag":96,"props":1504,"children":1505},{"style":130},[1506],{"type":29,"value":1507},"; ",{"type":24,"tag":96,"props":1509,"children":1510},{"style":103},[1511],{"type":29,"value":1512},"\u002F\u002F Aspetta che il group commit finisca\n",{"type":24,"tag":96,"props":1514,"children":1515},{"class":98,"line":601},[1516],{"type":24,"tag":96,"props":1517,"children":1518},{"style":130},[1519],{"type":29,"value":659},{"type":24,"tag":25,"props":1521,"children":1522},{},[1523,1528,1530,1535],{"type":24,"tag":692,"props":1524,"children":1525},{},[1526],{"type":29,"value":1527},"Abort:",{"type":29,"value":1529}," Rimuovi semplicemente la voce della transazione da ",{"type":24,"tag":92,"props":1531,"children":1533},{"className":1532},[],[1534],{"type":29,"value":177},{"type":29,"value":1536},". Le pagine dirty sono sparite. Nessun I\u002FO.",{"type":24,"tag":85,"props":1538,"children":1540},{"className":87,"code":1539,"language":89,"meta":7,"style":7},"public void AbortTransaction(ulong transactionId)\n{\n    _walCache.TryRemove(transactionId, out _);\n}\n",[1541],{"type":24,"tag":92,"props":1542,"children":1543},{"__ignoreMap":7},[1544,1576,1583,1623],{"type":24,"tag":96,"props":1545,"children":1546},{"class":98,"line":99},[1547,1551,1555,1560,1564,1568,1572],{"type":24,"tag":96,"props":1548,"children":1549},{"style":113},[1550],{"type":29,"value":318},{"type":24,"tag":96,"props":1552,"children":1553},{"style":113},[1554],{"type":29,"value":892},{"type":24,"tag":96,"props":1556,"children":1557},{"style":331},[1558],{"type":29,"value":1559}," AbortTransaction",{"type":24,"tag":96,"props":1561,"children":1562},{"style":130},[1563],{"type":29,"value":339},{"type":24,"tag":96,"props":1565,"children":1566},{"style":113},[1567],{"type":29,"value":138},{"type":24,"tag":96,"props":1569,"children":1570},{"style":124},[1571],{"type":29,"value":361},{"type":24,"tag":96,"props":1573,"children":1574},{"style":130},[1575],{"type":29,"value":366},{"type":24,"tag":96,"props":1577,"children":1578},{"class":98,"line":109},[1579],{"type":24,"tag":96,"props":1580,"children":1581},{"style":130},[1582],{"type":29,"value":374},{"type":24,"tag":96,"props":1584,"children":1585},{"class":98,"line":191},[1586,1590,1594,1598,1602,1606,1610,1614,1619],{"type":24,"tag":96,"props":1587,"children":1588},{"style":124},[1589],{"type":29,"value":791},{"type":24,"tag":96,"props":1591,"children":1592},{"style":130},[1593],{"type":29,"value":404},{"type":24,"tag":96,"props":1595,"children":1596},{"style":331},[1597],{"type":29,"value":1282},{"type":24,"tag":96,"props":1599,"children":1600},{"style":130},[1601],{"type":29,"value":339},{"type":24,"tag":96,"props":1603,"children":1604},{"style":174},[1605],{"type":29,"value":418},{"type":24,"tag":96,"props":1607,"children":1608},{"style":130},[1609],{"type":29,"value":143},{"type":24,"tag":96,"props":1611,"children":1612},{"style":113},[1613],{"type":29,"value":427},{"type":24,"tag":96,"props":1615,"children":1616},{"style":174},[1617],{"type":29,"value":1618}," _",{"type":24,"tag":96,"props":1620,"children":1621},{"style":130},[1622],{"type":29,"value":650},{"type":24,"tag":96,"props":1624,"children":1625},{"class":98,"line":201},[1626],{"type":24,"tag":96,"props":1627,"children":1628},{"style":130},[1629],{"type":29,"value":659},{"type":24,"tag":25,"props":1631,"children":1632},{},[1633],{"type":29,"value":1634},"Il rollback gratuito è un autentico vantaggio del design WAL cache. Non c'è nessun \"undo log\" da rieseguire, nessun ripristino di pagina da scrivere. I dati uncommitted non erano mai stati visibili a nessun altro e semplicemente cessano di esistere.",{"type":24,"tag":37,"props":1636,"children":1637},{},[],{"type":24,"tag":41,"props":1639,"children":1641},{"id":1640},"group-commit-da-_walcache-a-_walindex",[1642,1644,1649,1651],{"type":29,"value":1643},"Group Commit: Da ",{"type":24,"tag":92,"props":1645,"children":1647},{"className":1646},[],[1648],{"type":29,"value":177},{"type":29,"value":1650}," a ",{"type":24,"tag":92,"props":1652,"children":1654},{"className":1653},[],[1655],{"type":29,"value":249},{"type":24,"tag":25,"props":1657,"children":1658},{},[1659],{"type":29,"value":1660},"Il loop del group commit gira su un background task dedicato:",{"type":24,"tag":85,"props":1662,"children":1664},{"className":87,"code":1663,"language":89,"meta":7,"style":7},"private async Task GroupCommitLoopAsync(CancellationToken ct)\n{\n    await foreach (var pending in _commitChannel.Reader.ReadAllAsync(ct))\n    {\n        var batch = new List\u003CPendingCommit> { pending };\n\n        \u002F\u002F Drena eventuali commit aggiuntivi arrivati mentre eravamo in elaborazione\n        while (_commitChannel.Reader.TryRead(out var extra))\n            batch.Add(extra);\n\n        \u002F\u002F Scrivi tutte le pagine in batch nel WAL stream (singolo fsync)\n        await using var walLock = await _walLock.LockAsync();\n\n        foreach (var commit in batch)\n        {\n            WriteCommitToWalStream(commit);\n            \u002F\u002F Sposta le pagine committed nell'indice stabile\n            foreach (var (pageId, data) in commit.Pages)\n                _walIndex[pageId] = data;\n        }\n\n        await _walStream.FlushAsync();\n\n        \u002F\u002F Segnala tutti i waiter *fuori* dal lock\n        foreach (var commit in batch)\n            commit.Completion.TrySetResult();\n    }\n}\n",[1665],{"type":24,"tag":92,"props":1666,"children":1667},{"__ignoreMap":7},[1668,1706,1713,1779,1787,1835,1842,1850,1904,1934,1941,1949,1999,2006,2039,2048,2070,2079,2138,2172,2181,2189,2215,2223,2232,2264,2294,2303],{"type":24,"tag":96,"props":1669,"children":1670},{"class":98,"line":99},[1671,1675,1679,1683,1688,1692,1697,1702],{"type":24,"tag":96,"props":1672,"children":1673},{"style":113},[1674],{"type":29,"value":116},{"type":24,"tag":96,"props":1676,"children":1677},{"style":113},[1678],{"type":29,"value":1221},{"type":24,"tag":96,"props":1680,"children":1681},{"style":124},[1682],{"type":29,"value":1226},{"type":24,"tag":96,"props":1684,"children":1685},{"style":331},[1686],{"type":29,"value":1687}," GroupCommitLoopAsync",{"type":24,"tag":96,"props":1689,"children":1690},{"style":130},[1691],{"type":29,"value":339},{"type":24,"tag":96,"props":1693,"children":1694},{"style":124},[1695],{"type":29,"value":1696},"CancellationToken",{"type":24,"tag":96,"props":1698,"children":1699},{"style":124},[1700],{"type":29,"value":1701}," ct",{"type":24,"tag":96,"props":1703,"children":1704},{"style":130},[1705],{"type":29,"value":366},{"type":24,"tag":96,"props":1707,"children":1708},{"class":98,"line":109},[1709],{"type":24,"tag":96,"props":1710,"children":1711},{"style":130},[1712],{"type":29,"value":374},{"type":24,"tag":96,"props":1714,"children":1715},{"class":98,"line":191},[1716,1720,1725,1729,1734,1738,1743,1748,1752,1757,1761,1766,1770,1775],{"type":24,"tag":96,"props":1717,"children":1718},{"style":130},[1719],{"type":29,"value":1437},{"type":24,"tag":96,"props":1721,"children":1722},{"style":113},[1723],{"type":29,"value":1724},"foreach",{"type":24,"tag":96,"props":1726,"children":1727},{"style":130},[1728],{"type":29,"value":395},{"type":24,"tag":96,"props":1730,"children":1731},{"style":113},[1732],{"type":29,"value":1733},"var",{"type":24,"tag":96,"props":1735,"children":1736},{"style":174},[1737],{"type":29,"value":1356},{"type":24,"tag":96,"props":1739,"children":1740},{"style":113},[1741],{"type":29,"value":1742}," in",{"type":24,"tag":96,"props":1744,"children":1745},{"style":124},[1746],{"type":29,"value":1747}," _commitChannel",{"type":24,"tag":96,"props":1749,"children":1750},{"style":130},[1751],{"type":29,"value":404},{"type":24,"tag":96,"props":1753,"children":1754},{"style":124},[1755],{"type":29,"value":1756},"Reader",{"type":24,"tag":96,"props":1758,"children":1759},{"style":130},[1760],{"type":29,"value":404},{"type":24,"tag":96,"props":1762,"children":1763},{"style":331},[1764],{"type":29,"value":1765},"ReadAllAsync",{"type":24,"tag":96,"props":1767,"children":1768},{"style":130},[1769],{"type":29,"value":339},{"type":24,"tag":96,"props":1771,"children":1772},{"style":174},[1773],{"type":29,"value":1774},"ct",{"type":24,"tag":96,"props":1776,"children":1777},{"style":130},[1778],{"type":29,"value":494},{"type":24,"tag":96,"props":1780,"children":1781},{"class":98,"line":201},[1782],{"type":24,"tag":96,"props":1783,"children":1784},{"style":130},[1785],{"type":29,"value":1786},"    {\n",{"type":24,"tag":96,"props":1788,"children":1789},{"class":98,"line":210},[1790,1795,1800,1804,1808,1813,1817,1821,1826,1830],{"type":24,"tag":96,"props":1791,"children":1792},{"style":174},[1793],{"type":29,"value":1794},"        var",{"type":24,"tag":96,"props":1796,"children":1797},{"style":174},[1798],{"type":29,"value":1799}," batch",{"type":24,"tag":96,"props":1801,"children":1802},{"style":180},[1803],{"type":29,"value":183},{"type":24,"tag":96,"props":1805,"children":1806},{"style":130},[1807],{"type":29,"value":816},{"type":24,"tag":96,"props":1809,"children":1810},{"style":124},[1811],{"type":29,"value":1812},"List",{"type":24,"tag":96,"props":1814,"children":1815},{"style":130},[1816],{"type":29,"value":133},{"type":24,"tag":96,"props":1818,"children":1819},{"style":124},[1820],{"type":29,"value":1369},{"type":24,"tag":96,"props":1822,"children":1823},{"style":130},[1824],{"type":29,"value":1825},"> { ",{"type":24,"tag":96,"props":1827,"children":1828},{"style":174},[1829],{"type":29,"value":1469},{"type":24,"tag":96,"props":1831,"children":1832},{"style":130},[1833],{"type":29,"value":1834}," };\n",{"type":24,"tag":96,"props":1836,"children":1837},{"class":98,"line":497},[1838],{"type":24,"tag":96,"props":1839,"children":1840},{"emptyLinePlaceholder":195},[1841],{"type":29,"value":198},{"type":24,"tag":96,"props":1843,"children":1844},{"class":98,"line":515},[1845],{"type":24,"tag":96,"props":1846,"children":1847},{"style":103},[1848],{"type":29,"value":1849},"        \u002F\u002F Drena eventuali commit aggiuntivi arrivati mentre eravamo in elaborazione\n",{"type":24,"tag":96,"props":1851,"children":1852},{"class":98,"line":523},[1853,1858,1862,1866,1870,1874,1878,1883,1887,1891,1895,1900],{"type":24,"tag":96,"props":1854,"children":1855},{"style":331},[1856],{"type":29,"value":1857},"        while",{"type":24,"tag":96,"props":1859,"children":1860},{"style":130},[1861],{"type":29,"value":395},{"type":24,"tag":96,"props":1863,"children":1864},{"style":124},[1865],{"type":29,"value":1442},{"type":24,"tag":96,"props":1867,"children":1868},{"style":130},[1869],{"type":29,"value":404},{"type":24,"tag":96,"props":1871,"children":1872},{"style":124},[1873],{"type":29,"value":1756},{"type":24,"tag":96,"props":1875,"children":1876},{"style":130},[1877],{"type":29,"value":404},{"type":24,"tag":96,"props":1879,"children":1880},{"style":331},[1881],{"type":29,"value":1882},"TryRead",{"type":24,"tag":96,"props":1884,"children":1885},{"style":130},[1886],{"type":29,"value":339},{"type":24,"tag":96,"props":1888,"children":1889},{"style":113},[1890],{"type":29,"value":427},{"type":24,"tag":96,"props":1892,"children":1893},{"style":113},[1894],{"type":29,"value":432},{"type":24,"tag":96,"props":1896,"children":1897},{"style":174},[1898],{"type":29,"value":1899}," extra",{"type":24,"tag":96,"props":1901,"children":1902},{"style":130},[1903],{"type":29,"value":494},{"type":24,"tag":96,"props":1905,"children":1906},{"class":98,"line":532},[1907,1912,1916,1921,1925,1930],{"type":24,"tag":96,"props":1908,"children":1909},{"style":124},[1910],{"type":29,"value":1911},"            batch",{"type":24,"tag":96,"props":1913,"children":1914},{"style":130},[1915],{"type":29,"value":404},{"type":24,"tag":96,"props":1917,"children":1918},{"style":331},[1919],{"type":29,"value":1920},"Add",{"type":24,"tag":96,"props":1922,"children":1923},{"style":130},[1924],{"type":29,"value":339},{"type":24,"tag":96,"props":1926,"children":1927},{"style":174},[1928],{"type":29,"value":1929},"extra",{"type":24,"tag":96,"props":1931,"children":1932},{"style":130},[1933],{"type":29,"value":650},{"type":24,"tag":96,"props":1935,"children":1936},{"class":98,"line":585},[1937],{"type":24,"tag":96,"props":1938,"children":1939},{"emptyLinePlaceholder":195},[1940],{"type":29,"value":198},{"type":24,"tag":96,"props":1942,"children":1943},{"class":98,"line":601},[1944],{"type":24,"tag":96,"props":1945,"children":1946},{"style":103},[1947],{"type":29,"value":1948},"        \u002F\u002F Scrivi tutte le pagine in batch nel WAL stream (singolo fsync)\n",{"type":24,"tag":96,"props":1950,"children":1951},{"class":98,"line":609},[1952,1957,1962,1966,1971,1975,1980,1985,1989,1994],{"type":24,"tag":96,"props":1953,"children":1954},{"style":130},[1955],{"type":29,"value":1956},"        await ",{"type":24,"tag":96,"props":1958,"children":1959},{"style":174},[1960],{"type":29,"value":1961},"using",{"type":24,"tag":96,"props":1963,"children":1964},{"style":174},[1965],{"type":29,"value":432},{"type":24,"tag":96,"props":1967,"children":1968},{"style":174},[1969],{"type":29,"value":1970}," walLock",{"type":24,"tag":96,"props":1972,"children":1973},{"style":180},[1974],{"type":29,"value":183},{"type":24,"tag":96,"props":1976,"children":1977},{"style":130},[1978],{"type":29,"value":1979}," await ",{"type":24,"tag":96,"props":1981,"children":1982},{"style":124},[1983],{"type":29,"value":1984},"_walLock",{"type":24,"tag":96,"props":1986,"children":1987},{"style":130},[1988],{"type":29,"value":404},{"type":24,"tag":96,"props":1990,"children":1991},{"style":331},[1992],{"type":29,"value":1993},"LockAsync",{"type":24,"tag":96,"props":1995,"children":1996},{"style":130},[1997],{"type":29,"value":1998},"();\n",{"type":24,"tag":96,"props":2000,"children":2001},{"class":98,"line":618},[2002],{"type":24,"tag":96,"props":2003,"children":2004},{"emptyLinePlaceholder":195},[2005],{"type":29,"value":198},{"type":24,"tag":96,"props":2007,"children":2008},{"class":98,"line":653},[2009,2014,2018,2022,2027,2031,2035],{"type":24,"tag":96,"props":2010,"children":2011},{"style":331},[2012],{"type":29,"value":2013},"        foreach",{"type":24,"tag":96,"props":2015,"children":2016},{"style":130},[2017],{"type":29,"value":395},{"type":24,"tag":96,"props":2019,"children":2020},{"style":174},[2021],{"type":29,"value":1733},{"type":24,"tag":96,"props":2023,"children":2024},{"style":174},[2025],{"type":29,"value":2026}," commit",{"type":24,"tag":96,"props":2028,"children":2029},{"style":113},[2030],{"type":29,"value":1742},{"type":24,"tag":96,"props":2032,"children":2033},{"style":174},[2034],{"type":29,"value":1799},{"type":24,"tag":96,"props":2036,"children":2037},{"style":130},[2038],{"type":29,"value":366},{"type":24,"tag":96,"props":2040,"children":2042},{"class":98,"line":2041},15,[2043],{"type":24,"tag":96,"props":2044,"children":2045},{"style":130},[2046],{"type":29,"value":2047},"        {\n",{"type":24,"tag":96,"props":2049,"children":2051},{"class":98,"line":2050},16,[2052,2057,2061,2066],{"type":24,"tag":96,"props":2053,"children":2054},{"style":331},[2055],{"type":29,"value":2056},"            WriteCommitToWalStream",{"type":24,"tag":96,"props":2058,"children":2059},{"style":130},[2060],{"type":29,"value":339},{"type":24,"tag":96,"props":2062,"children":2063},{"style":174},[2064],{"type":29,"value":2065},"commit",{"type":24,"tag":96,"props":2067,"children":2068},{"style":130},[2069],{"type":29,"value":650},{"type":24,"tag":96,"props":2071,"children":2073},{"class":98,"line":2072},17,[2074],{"type":24,"tag":96,"props":2075,"children":2076},{"style":103},[2077],{"type":29,"value":2078},"            \u002F\u002F Sposta le pagine committed nell'indice stabile\n",{"type":24,"tag":96,"props":2080,"children":2082},{"class":98,"line":2081},18,[2083,2088,2092,2096,2100,2104,2108,2112,2116,2121,2125,2129,2134],{"type":24,"tag":96,"props":2084,"children":2085},{"style":331},[2086],{"type":29,"value":2087},"            foreach",{"type":24,"tag":96,"props":2089,"children":2090},{"style":130},[2091],{"type":29,"value":395},{"type":24,"tag":96,"props":2093,"children":2094},{"style":331},[2095],{"type":29,"value":1733},{"type":24,"tag":96,"props":2097,"children":2098},{"style":130},[2099],{"type":29,"value":395},{"type":24,"tag":96,"props":2101,"children":2102},{"style":174},[2103],{"type":29,"value":472},{"type":24,"tag":96,"props":2105,"children":2106},{"style":130},[2107],{"type":29,"value":143},{"type":24,"tag":96,"props":2109,"children":2110},{"style":174},[2111],{"type":29,"value":926},{"type":24,"tag":96,"props":2113,"children":2114},{"style":130},[2115],{"type":29,"value":442},{"type":24,"tag":96,"props":2117,"children":2118},{"style":113},[2119],{"type":29,"value":2120},"in",{"type":24,"tag":96,"props":2122,"children":2123},{"style":124},[2124],{"type":29,"value":2026},{"type":24,"tag":96,"props":2126,"children":2127},{"style":130},[2128],{"type":29,"value":404},{"type":24,"tag":96,"props":2130,"children":2131},{"style":124},[2132],{"type":29,"value":2133},"Pages",{"type":24,"tag":96,"props":2135,"children":2136},{"style":130},[2137],{"type":29,"value":366},{"type":24,"tag":96,"props":2139,"children":2141},{"class":98,"line":2140},19,[2142,2147,2151,2155,2159,2163,2168],{"type":24,"tag":96,"props":2143,"children":2144},{"style":124},[2145],{"type":29,"value":2146},"                _walIndex",{"type":24,"tag":96,"props":2148,"children":2149},{"style":130},[2150],{"type":29,"value":796},{"type":24,"tag":96,"props":2152,"children":2153},{"style":174},[2154],{"type":29,"value":472},{"type":24,"tag":96,"props":2156,"children":2157},{"style":130},[2158],{"type":29,"value":806},{"type":24,"tag":96,"props":2160,"children":2161},{"style":180},[2162],{"type":29,"value":811},{"type":24,"tag":96,"props":2164,"children":2165},{"style":174},[2166],{"type":29,"value":2167}," data",{"type":24,"tag":96,"props":2169,"children":2170},{"style":130},[2171],{"type":29,"value":512},{"type":24,"tag":96,"props":2173,"children":2175},{"class":98,"line":2174},20,[2176],{"type":24,"tag":96,"props":2177,"children":2178},{"style":130},[2179],{"type":29,"value":2180},"        }\n",{"type":24,"tag":96,"props":2182,"children":2184},{"class":98,"line":2183},21,[2185],{"type":24,"tag":96,"props":2186,"children":2187},{"emptyLinePlaceholder":195},[2188],{"type":29,"value":198},{"type":24,"tag":96,"props":2190,"children":2192},{"class":98,"line":2191},22,[2193,2197,2202,2206,2211],{"type":24,"tag":96,"props":2194,"children":2195},{"style":130},[2196],{"type":29,"value":1956},{"type":24,"tag":96,"props":2198,"children":2199},{"style":124},[2200],{"type":29,"value":2201},"_walStream",{"type":24,"tag":96,"props":2203,"children":2204},{"style":130},[2205],{"type":29,"value":404},{"type":24,"tag":96,"props":2207,"children":2208},{"style":331},[2209],{"type":29,"value":2210},"FlushAsync",{"type":24,"tag":96,"props":2212,"children":2213},{"style":130},[2214],{"type":29,"value":1998},{"type":24,"tag":96,"props":2216,"children":2218},{"class":98,"line":2217},23,[2219],{"type":24,"tag":96,"props":2220,"children":2221},{"emptyLinePlaceholder":195},[2222],{"type":29,"value":198},{"type":24,"tag":96,"props":2224,"children":2226},{"class":98,"line":2225},24,[2227],{"type":24,"tag":96,"props":2228,"children":2229},{"style":103},[2230],{"type":29,"value":2231},"        \u002F\u002F Segnala tutti i waiter *fuori* dal lock\n",{"type":24,"tag":96,"props":2233,"children":2235},{"class":98,"line":2234},25,[2236,2240,2244,2248,2252,2256,2260],{"type":24,"tag":96,"props":2237,"children":2238},{"style":331},[2239],{"type":29,"value":2013},{"type":24,"tag":96,"props":2241,"children":2242},{"style":130},[2243],{"type":29,"value":395},{"type":24,"tag":96,"props":2245,"children":2246},{"style":174},[2247],{"type":29,"value":1733},{"type":24,"tag":96,"props":2249,"children":2250},{"style":174},[2251],{"type":29,"value":2026},{"type":24,"tag":96,"props":2253,"children":2254},{"style":113},[2255],{"type":29,"value":1742},{"type":24,"tag":96,"props":2257,"children":2258},{"style":174},[2259],{"type":29,"value":1799},{"type":24,"tag":96,"props":2261,"children":2262},{"style":130},[2263],{"type":29,"value":366},{"type":24,"tag":96,"props":2265,"children":2267},{"class":98,"line":2266},26,[2268,2273,2277,2281,2285,2290],{"type":24,"tag":96,"props":2269,"children":2270},{"style":124},[2271],{"type":29,"value":2272},"            commit",{"type":24,"tag":96,"props":2274,"children":2275},{"style":130},[2276],{"type":29,"value":404},{"type":24,"tag":96,"props":2278,"children":2279},{"style":124},[2280],{"type":29,"value":1493},{"type":24,"tag":96,"props":2282,"children":2283},{"style":130},[2284],{"type":29,"value":404},{"type":24,"tag":96,"props":2286,"children":2287},{"style":331},[2288],{"type":29,"value":2289},"TrySetResult",{"type":24,"tag":96,"props":2291,"children":2292},{"style":130},[2293],{"type":29,"value":1998},{"type":24,"tag":96,"props":2295,"children":2297},{"class":98,"line":2296},27,[2298],{"type":24,"tag":96,"props":2299,"children":2300},{"style":130},[2301],{"type":29,"value":2302},"    }\n",{"type":24,"tag":96,"props":2304,"children":2306},{"class":98,"line":2305},28,[2307],{"type":24,"tag":96,"props":2308,"children":2309},{"style":130},[2310],{"type":29,"value":659},{"type":24,"tag":25,"props":2312,"children":2313},{},[2314,2316,2321],{"type":29,"value":2315},"Tutte le transazioni nel batch condividono una singola chiamata ",{"type":24,"tag":92,"props":2317,"children":2319},{"className":2318},[],[2320],{"type":29,"value":2210},{"type":29,"value":2322},". Questo è il dividendo del group commit: invece di un fsync per commit (un'operazione disco di ~10ms), N transazioni condividono un fsync a ~10ms totali. Ad alti tassi di commit, questa è la differenza tra 100 commit\u002Fsec e 10.000 commit\u002Fsec.",{"type":24,"tag":37,"props":2324,"children":2325},{},[],{"type":24,"tag":41,"props":2327,"children":2329},{"id":2328},"perché-semaphoreslim-sul-wal-stream",[2330,2332,2338],{"type":29,"value":2331},"Perché ",{"type":24,"tag":92,"props":2333,"children":2335},{"className":2334},[],[2336],{"type":29,"value":2337},"SemaphoreSlim",{"type":29,"value":2339}," sul WAL Stream",{"type":24,"tag":25,"props":2341,"children":2342},{},[2343,2345,2350],{"type":29,"value":2344},"Il WAL stream è stato condiviso. Qualsiasi iterazione concorrente del loop di commit lo corromperebbe. BLite usa un async lock basato su ",{"type":24,"tag":92,"props":2346,"children":2348},{"className":2347},[],[2349],{"type":29,"value":2337},{"type":29,"value":2351},":",{"type":24,"tag":85,"props":2353,"children":2355},{"className":87,"code":2354,"language":89,"meta":7,"style":7},"private readonly SemaphoreSlim _walLock = new(1, 1);\n\n\u002F\u002F Wrapper comodo che rilascia il semaforo all'uscita\nprivate async Task\u003CIDisposable> LockAsync()\n{\n    await _walLock.WaitAsync();\n    return new SemaphoreReleaser(_walLock);\n}\n",[2356],{"type":24,"tag":92,"props":2357,"children":2358},{"__ignoreMap":7},[2359,2406,2413,2421,2458,2465,2489,2517],{"type":24,"tag":96,"props":2360,"children":2361},{"class":98,"line":99},[2362,2366,2370,2375,2380,2384,2389,2394,2398,2402],{"type":24,"tag":96,"props":2363,"children":2364},{"style":113},[2365],{"type":29,"value":116},{"type":24,"tag":96,"props":2367,"children":2368},{"style":113},[2369],{"type":29,"value":121},{"type":24,"tag":96,"props":2371,"children":2372},{"style":124},[2373],{"type":29,"value":2374}," SemaphoreSlim",{"type":24,"tag":96,"props":2376,"children":2377},{"style":174},[2378],{"type":29,"value":2379}," _walLock",{"type":24,"tag":96,"props":2381,"children":2382},{"style":180},[2383],{"type":29,"value":183},{"type":24,"tag":96,"props":2385,"children":2386},{"style":130},[2387],{"type":29,"value":2388}," new(",{"type":24,"tag":96,"props":2390,"children":2391},{"style":1131},[2392],{"type":29,"value":2393},"1",{"type":24,"tag":96,"props":2395,"children":2396},{"style":130},[2397],{"type":29,"value":143},{"type":24,"tag":96,"props":2399,"children":2400},{"style":1131},[2401],{"type":29,"value":2393},{"type":24,"tag":96,"props":2403,"children":2404},{"style":130},[2405],{"type":29,"value":650},{"type":24,"tag":96,"props":2407,"children":2408},{"class":98,"line":109},[2409],{"type":24,"tag":96,"props":2410,"children":2411},{"emptyLinePlaceholder":195},[2412],{"type":29,"value":198},{"type":24,"tag":96,"props":2414,"children":2415},{"class":98,"line":191},[2416],{"type":24,"tag":96,"props":2417,"children":2418},{"style":103},[2419],{"type":29,"value":2420},"\u002F\u002F Wrapper comodo che rilascia il semaforo all'uscita\n",{"type":24,"tag":96,"props":2422,"children":2423},{"class":98,"line":201},[2424,2428,2432,2436,2440,2445,2450,2454],{"type":24,"tag":96,"props":2425,"children":2426},{"style":113},[2427],{"type":29,"value":116},{"type":24,"tag":96,"props":2429,"children":2430},{"style":113},[2431],{"type":29,"value":1221},{"type":24,"tag":96,"props":2433,"children":2434},{"style":124},[2435],{"type":29,"value":1226},{"type":24,"tag":96,"props":2437,"children":2438},{"style":130},[2439],{"type":29,"value":133},{"type":24,"tag":96,"props":2441,"children":2442},{"style":124},[2443],{"type":29,"value":2444},"IDisposable",{"type":24,"tag":96,"props":2446,"children":2447},{"style":130},[2448],{"type":29,"value":2449},"> ",{"type":24,"tag":96,"props":2451,"children":2452},{"style":331},[2453],{"type":29,"value":1993},{"type":24,"tag":96,"props":2455,"children":2456},{"style":130},[2457],{"type":29,"value":727},{"type":24,"tag":96,"props":2459,"children":2460},{"class":98,"line":210},[2461],{"type":24,"tag":96,"props":2462,"children":2463},{"style":130},[2464],{"type":29,"value":374},{"type":24,"tag":96,"props":2466,"children":2467},{"class":98,"line":497},[2468,2472,2476,2480,2485],{"type":24,"tag":96,"props":2469,"children":2470},{"style":130},[2471],{"type":29,"value":1437},{"type":24,"tag":96,"props":2473,"children":2474},{"style":124},[2475],{"type":29,"value":1984},{"type":24,"tag":96,"props":2477,"children":2478},{"style":130},[2479],{"type":29,"value":404},{"type":24,"tag":96,"props":2481,"children":2482},{"style":331},[2483],{"type":29,"value":2484},"WaitAsync",{"type":24,"tag":96,"props":2486,"children":2487},{"style":130},[2488],{"type":29,"value":1998},{"type":24,"tag":96,"props":2490,"children":2491},{"class":98,"line":515},[2492,2496,2500,2505,2509,2513],{"type":24,"tag":96,"props":2493,"children":2494},{"style":113},[2495],{"type":29,"value":624},{"type":24,"tag":96,"props":2497,"children":2498},{"style":130},[2499],{"type":29,"value":816},{"type":24,"tag":96,"props":2501,"children":2502},{"style":124},[2503],{"type":29,"value":2504},"SemaphoreReleaser",{"type":24,"tag":96,"props":2506,"children":2507},{"style":130},[2508],{"type":29,"value":339},{"type":24,"tag":96,"props":2510,"children":2511},{"style":174},[2512],{"type":29,"value":1984},{"type":24,"tag":96,"props":2514,"children":2515},{"style":130},[2516],{"type":29,"value":650},{"type":24,"tag":96,"props":2518,"children":2519},{"class":98,"line":523},[2520],{"type":24,"tag":96,"props":2521,"children":2522},{"style":130},[2523],{"type":29,"value":659},{"type":24,"tag":25,"props":2525,"children":2526},{},[2527,2532,2534,2540,2542,2547],{"type":24,"tag":92,"props":2528,"children":2530},{"className":2529},[],[2531],{"type":29,"value":2337},{"type":29,"value":2533}," con contatore iniziale 1 è il mutex async idiomatico in .NET. A differenza di ",{"type":24,"tag":92,"props":2535,"children":2537},{"className":2536},[],[2538],{"type":29,"value":2539},"lock",{"type":29,"value":2541},", non blocca un thread mentre aspetta — cede il controllo al thread pool, il che conta quando il lock è tenuto durante ",{"type":24,"tag":92,"props":2543,"children":2545},{"className":2544},[],[2546],{"type":29,"value":2210},{"type":29,"value":2548}," (un'operazione async che causerebbe un deadlock con un lock sincrono).",{"type":24,"tag":37,"props":2550,"children":2551},{},[],{"type":24,"tag":41,"props":2553,"children":2555},{"id":2554},"checkpoint-collassare-il-wal-nel-page-file",[2556],{"type":29,"value":2557},"Checkpoint: Collassare il WAL nel Page File",{"type":24,"tag":25,"props":2559,"children":2560},{},[2561,2563,2568,2570,2575],{"type":29,"value":2562},"Man mano che le transazioni vengono committate, ",{"type":24,"tag":92,"props":2564,"children":2566},{"className":2565},[],[2567],{"type":29,"value":249},{"type":29,"value":2569}," cresce. Alla fine diventa abbastanza grande da rendere inaccettabile il tempo di avvio (riapplicazione del WAL) durante il recovery. Un checkpoint unisce il ",{"type":24,"tag":92,"props":2571,"children":2573},{"className":2572},[],[2574],{"type":29,"value":249},{"type":29,"value":2576}," nel file di pagine durevole e tronca il WAL:",{"type":24,"tag":85,"props":2578,"children":2580},{"className":87,"code":2579,"language":89,"meta":7,"style":7},"private async Task CheckpointInternalAsync(CancellationToken ct)\n{\n    await using var walLock = await _walLock.LockAsync();\n\n    \u002F\u002F Scrivi tutte le pagine stabili nel page file\n    foreach (var (pageId, data) in _walIndex)\n        await _pageFile.WritePageAsync(pageId, data, ct);\n\n    await _pageFile.FlushAsync(ct);\n\n    \u002F\u002F Ora è sicuro troncare il WAL\n    _walStream.SetLength(0);\n    _walStream.Seek(0, SeekOrigin.Begin);\n    _walIndex.Clear();\n}\n",[2581],{"type":24,"tag":92,"props":2582,"children":2583},{"__ignoreMap":7},[2584,2620,2627,2670,2677,2685,2719,2768,2775,2806,2813,2821,2850,2896,2917],{"type":24,"tag":96,"props":2585,"children":2586},{"class":98,"line":99},[2587,2591,2595,2599,2604,2608,2612,2616],{"type":24,"tag":96,"props":2588,"children":2589},{"style":113},[2590],{"type":29,"value":116},{"type":24,"tag":96,"props":2592,"children":2593},{"style":113},[2594],{"type":29,"value":1221},{"type":24,"tag":96,"props":2596,"children":2597},{"style":124},[2598],{"type":29,"value":1226},{"type":24,"tag":96,"props":2600,"children":2601},{"style":331},[2602],{"type":29,"value":2603}," CheckpointInternalAsync",{"type":24,"tag":96,"props":2605,"children":2606},{"style":130},[2607],{"type":29,"value":339},{"type":24,"tag":96,"props":2609,"children":2610},{"style":124},[2611],{"type":29,"value":1696},{"type":24,"tag":96,"props":2613,"children":2614},{"style":124},[2615],{"type":29,"value":1701},{"type":24,"tag":96,"props":2617,"children":2618},{"style":130},[2619],{"type":29,"value":366},{"type":24,"tag":96,"props":2621,"children":2622},{"class":98,"line":109},[2623],{"type":24,"tag":96,"props":2624,"children":2625},{"style":130},[2626],{"type":29,"value":374},{"type":24,"tag":96,"props":2628,"children":2629},{"class":98,"line":191},[2630,2634,2638,2642,2646,2650,2654,2658,2662,2666],{"type":24,"tag":96,"props":2631,"children":2632},{"style":130},[2633],{"type":29,"value":1437},{"type":24,"tag":96,"props":2635,"children":2636},{"style":113},[2637],{"type":29,"value":1961},{"type":24,"tag":96,"props":2639,"children":2640},{"style":113},[2641],{"type":29,"value":432},{"type":24,"tag":96,"props":2643,"children":2644},{"style":174},[2645],{"type":29,"value":1970},{"type":24,"tag":96,"props":2647,"children":2648},{"style":180},[2649],{"type":29,"value":183},{"type":24,"tag":96,"props":2651,"children":2652},{"style":130},[2653],{"type":29,"value":1979},{"type":24,"tag":96,"props":2655,"children":2656},{"style":124},[2657],{"type":29,"value":1984},{"type":24,"tag":96,"props":2659,"children":2660},{"style":130},[2661],{"type":29,"value":404},{"type":24,"tag":96,"props":2663,"children":2664},{"style":331},[2665],{"type":29,"value":1993},{"type":24,"tag":96,"props":2667,"children":2668},{"style":130},[2669],{"type":29,"value":1998},{"type":24,"tag":96,"props":2671,"children":2672},{"class":98,"line":201},[2673],{"type":24,"tag":96,"props":2674,"children":2675},{"emptyLinePlaceholder":195},[2676],{"type":29,"value":198},{"type":24,"tag":96,"props":2678,"children":2679},{"class":98,"line":210},[2680],{"type":24,"tag":96,"props":2681,"children":2682},{"style":103},[2683],{"type":29,"value":2684},"    \u002F\u002F Scrivi tutte le pagine stabili nel page file\n",{"type":24,"tag":96,"props":2686,"children":2687},{"class":98,"line":497},[2688,2693,2697,2701,2706,2710,2715],{"type":24,"tag":96,"props":2689,"children":2690},{"style":113},[2691],{"type":29,"value":2692},"    foreach",{"type":24,"tag":96,"props":2694,"children":2695},{"style":130},[2696],{"type":29,"value":395},{"type":24,"tag":96,"props":2698,"children":2699},{"style":113},[2700],{"type":29,"value":1733},{"type":24,"tag":96,"props":2702,"children":2703},{"style":130},[2704],{"type":29,"value":2705}," (pageId, data) ",{"type":24,"tag":96,"props":2707,"children":2708},{"style":113},[2709],{"type":29,"value":2120},{"type":24,"tag":96,"props":2711,"children":2712},{"style":174},[2713],{"type":29,"value":2714}," _walIndex",{"type":24,"tag":96,"props":2716,"children":2717},{"style":130},[2718],{"type":29,"value":366},{"type":24,"tag":96,"props":2720,"children":2721},{"class":98,"line":515},[2722,2726,2731,2735,2740,2744,2748,2752,2756,2760,2764],{"type":24,"tag":96,"props":2723,"children":2724},{"style":130},[2725],{"type":29,"value":1956},{"type":24,"tag":96,"props":2727,"children":2728},{"style":124},[2729],{"type":29,"value":2730},"_pageFile",{"type":24,"tag":96,"props":2732,"children":2733},{"style":130},[2734],{"type":29,"value":404},{"type":24,"tag":96,"props":2736,"children":2737},{"style":331},[2738],{"type":29,"value":2739},"WritePageAsync",{"type":24,"tag":96,"props":2741,"children":2742},{"style":130},[2743],{"type":29,"value":339},{"type":24,"tag":96,"props":2745,"children":2746},{"style":174},[2747],{"type":29,"value":472},{"type":24,"tag":96,"props":2749,"children":2750},{"style":130},[2751],{"type":29,"value":143},{"type":24,"tag":96,"props":2753,"children":2754},{"style":174},[2755],{"type":29,"value":926},{"type":24,"tag":96,"props":2757,"children":2758},{"style":130},[2759],{"type":29,"value":143},{"type":24,"tag":96,"props":2761,"children":2762},{"style":174},[2763],{"type":29,"value":1774},{"type":24,"tag":96,"props":2765,"children":2766},{"style":130},[2767],{"type":29,"value":650},{"type":24,"tag":96,"props":2769,"children":2770},{"class":98,"line":523},[2771],{"type":24,"tag":96,"props":2772,"children":2773},{"emptyLinePlaceholder":195},[2774],{"type":29,"value":198},{"type":24,"tag":96,"props":2776,"children":2777},{"class":98,"line":532},[2778,2782,2786,2790,2794,2798,2802],{"type":24,"tag":96,"props":2779,"children":2780},{"style":130},[2781],{"type":29,"value":1437},{"type":24,"tag":96,"props":2783,"children":2784},{"style":124},[2785],{"type":29,"value":2730},{"type":24,"tag":96,"props":2787,"children":2788},{"style":130},[2789],{"type":29,"value":404},{"type":24,"tag":96,"props":2791,"children":2792},{"style":331},[2793],{"type":29,"value":2210},{"type":24,"tag":96,"props":2795,"children":2796},{"style":130},[2797],{"type":29,"value":339},{"type":24,"tag":96,"props":2799,"children":2800},{"style":174},[2801],{"type":29,"value":1774},{"type":24,"tag":96,"props":2803,"children":2804},{"style":130},[2805],{"type":29,"value":650},{"type":24,"tag":96,"props":2807,"children":2808},{"class":98,"line":585},[2809],{"type":24,"tag":96,"props":2810,"children":2811},{"emptyLinePlaceholder":195},[2812],{"type":29,"value":198},{"type":24,"tag":96,"props":2814,"children":2815},{"class":98,"line":601},[2816],{"type":24,"tag":96,"props":2817,"children":2818},{"style":103},[2819],{"type":29,"value":2820},"    \u002F\u002F Ora è sicuro troncare il WAL\n",{"type":24,"tag":96,"props":2822,"children":2823},{"class":98,"line":609},[2824,2829,2833,2838,2842,2846],{"type":24,"tag":96,"props":2825,"children":2826},{"style":124},[2827],{"type":29,"value":2828},"    _walStream",{"type":24,"tag":96,"props":2830,"children":2831},{"style":130},[2832],{"type":29,"value":404},{"type":24,"tag":96,"props":2834,"children":2835},{"style":331},[2836],{"type":29,"value":2837},"SetLength",{"type":24,"tag":96,"props":2839,"children":2840},{"style":130},[2841],{"type":29,"value":339},{"type":24,"tag":96,"props":2843,"children":2844},{"style":1131},[2845],{"type":29,"value":1134},{"type":24,"tag":96,"props":2847,"children":2848},{"style":130},[2849],{"type":29,"value":650},{"type":24,"tag":96,"props":2851,"children":2852},{"class":98,"line":618},[2853,2857,2861,2866,2870,2874,2878,2883,2887,2892],{"type":24,"tag":96,"props":2854,"children":2855},{"style":124},[2856],{"type":29,"value":2828},{"type":24,"tag":96,"props":2858,"children":2859},{"style":130},[2860],{"type":29,"value":404},{"type":24,"tag":96,"props":2862,"children":2863},{"style":331},[2864],{"type":29,"value":2865},"Seek",{"type":24,"tag":96,"props":2867,"children":2868},{"style":130},[2869],{"type":29,"value":339},{"type":24,"tag":96,"props":2871,"children":2872},{"style":1131},[2873],{"type":29,"value":1134},{"type":24,"tag":96,"props":2875,"children":2876},{"style":130},[2877],{"type":29,"value":143},{"type":24,"tag":96,"props":2879,"children":2880},{"style":124},[2881],{"type":29,"value":2882},"SeekOrigin",{"type":24,"tag":96,"props":2884,"children":2885},{"style":130},[2886],{"type":29,"value":404},{"type":24,"tag":96,"props":2888,"children":2889},{"style":124},[2890],{"type":29,"value":2891},"Begin",{"type":24,"tag":96,"props":2893,"children":2894},{"style":130},[2895],{"type":29,"value":650},{"type":24,"tag":96,"props":2897,"children":2898},{"class":98,"line":653},[2899,2904,2908,2913],{"type":24,"tag":96,"props":2900,"children":2901},{"style":124},[2902],{"type":29,"value":2903},"    _walIndex",{"type":24,"tag":96,"props":2905,"children":2906},{"style":130},[2907],{"type":29,"value":404},{"type":24,"tag":96,"props":2909,"children":2910},{"style":331},[2911],{"type":29,"value":2912},"Clear",{"type":24,"tag":96,"props":2914,"children":2915},{"style":130},[2916],{"type":29,"value":1998},{"type":24,"tag":96,"props":2918,"children":2919},{"class":98,"line":2041},[2920],{"type":24,"tag":96,"props":2921,"children":2922},{"style":130},[2923],{"type":29,"value":659},{"type":24,"tag":25,"props":2925,"children":2926},{},[2927,2929,2934,2936,2941],{"type":29,"value":2928},"Il checkpointing è serializzato sotto ",{"type":24,"tag":92,"props":2930,"children":2932},{"className":2931},[],[2933],{"type":29,"value":1984},{"type":29,"value":2935},", il che significa che blocca il loop del group commit. Durante un checkpoint, le chiamate di commit in arrivo si accodano in ",{"type":24,"tag":92,"props":2937,"children":2939},{"className":2938},[],[2940],{"type":29,"value":1442},{"type":29,"value":2942}," e riprendono una volta rilasciato il lock. La durata del lock è proporzionale al numero di pagine dirty — un altro argomento per checkpoint piccoli e frequenti rispetto a quelli rari e grandi.",{"type":24,"tag":37,"props":2944,"children":2945},{},[],{"type":24,"tag":41,"props":2947,"children":2949},{"id":2948},"dove-questo-si-discosta-dal-vero-mvcc",[2950],{"type":29,"value":2951},"Dove Questo Si Discosta dal Vero MVCC",{"type":24,"tag":25,"props":2953,"children":2954},{},[2955],{"type":29,"value":2956},"Il modello di BLite ti dà le proprietà ACID che contano per un database embedded:",{"type":24,"tag":2958,"props":2959,"children":2960},"ul",{},[2961,2972,2982,2992],{"type":24,"tag":2962,"props":2963,"children":2964},"li",{},[2965,2970],{"type":24,"tag":692,"props":2966,"children":2967},{},[2968],{"type":29,"value":2969},"Atomicità",{"type":29,"value":2971},": le pagine uncommitted sono invisibili; il rollback è gratuito.",{"type":24,"tag":2962,"props":2973,"children":2974},{},[2975,2980],{"type":24,"tag":692,"props":2976,"children":2977},{},[2978],{"type":29,"value":2979},"Consistenza",{"type":29,"value":2981},": i vincoli sono applicati al livello del documento prima che le pagine vengano scritte.",{"type":24,"tag":2962,"props":2983,"children":2984},{},[2985,2990],{"type":24,"tag":692,"props":2986,"children":2987},{},[2988],{"type":29,"value":2989},"Isolamento",{"type":29,"value":2991},": ogni transazione legge una vista coerente — le proprie scritture sovrapposte allo stato dell'ultimo committed.",{"type":24,"tag":2962,"props":2993,"children":2994},{},[2995,3000,3002,3007],{"type":24,"tag":692,"props":2996,"children":2997},{},[2998],{"type":29,"value":2999},"Durabilità",{"type":29,"value":3001},": le transazioni committed sopravvivono a un crash perché sono nel WAL prima che ",{"type":24,"tag":92,"props":3003,"children":3005},{"className":3004},[],[3006],{"type":29,"value":2289},{"type":29,"value":3008}," scatti.",{"type":24,"tag":25,"props":3010,"children":3011},{},[3012],{"type":29,"value":3013},"Ma non è MVCC completo nel senso della teoria dei database:",{"type":24,"tag":25,"props":3015,"children":3016},{},[3017,3022,3024,3029],{"type":24,"tag":692,"props":3018,"children":3019},{},[3020],{"type":29,"value":3021},"Nessun snapshot isolation.",{"type":29,"value":3023}," Due lettori concorrenti non vedono ciascuno lo stato del database ai loro singoli tempi di inizio. Entrambi leggono dallo stesso snapshot ",{"type":24,"tag":92,"props":3025,"children":3027},{"className":3026},[],[3028],{"type":29,"value":249},{"type":29,"value":3030}," — lo stato dell'ultima transazione committata. Se la transazione A legge la pagina 5, poi la transazione B committe un aggiornamento alla pagina 5, poi la transazione A legge di nuovo la pagina 5, vedrà l'aggiornamento committato di B. Questo è l'isolamento \"read committed\", non \"repeatable read\" o \"serializable.\"",{"type":24,"tag":25,"props":3032,"children":3033},{},[3034,3039,3041,3046,3048,3053],{"type":24,"tag":692,"props":3035,"children":3036},{},[3037],{"type":29,"value":3038},"Singolo scrittore logico.",{"type":29,"value":3040}," I commit sono serializzati attraverso ",{"type":24,"tag":92,"props":3042,"children":3044},{"className":3043},[],[3045],{"type":29,"value":1442},{"type":29,"value":3047},". Le transazioni concorrenti possono preparare le loro pagine dirty in parallelo (ciascuna nella propria voce ",{"type":24,"tag":92,"props":3049,"children":3051},{"className":3050},[],[3052],{"type":29,"value":177},{"type":29,"value":3054},") ma solo un commit alla volta passa attraverso il loop del group commit. Non c'è percorso di scrittura concorrente — il \"group\" nel group commit significa raggruppamento, non parallelismo.",{"type":24,"tag":25,"props":3056,"children":3057},{},[3058,3063,3065,3070],{"type":24,"tag":692,"props":3059,"children":3060},{},[3061],{"type":29,"value":3062},"I lettori possono stallare durante il checkpoint.",{"type":29,"value":3064}," Il loop di checkpoint tiene ",{"type":24,"tag":92,"props":3066,"children":3068},{"className":3067},[],[3069],{"type":29,"value":1984},{"type":29,"value":3071},", che serializza rispetto al loop di commit, che serializza rispetto a tutti i nuovi commit. Un checkpoint lungo può ritardare tutti i nuovi commit per la sua durata. Un sistema MVCC appropriato permetterebbe ai lettori di procedere contro le vecchie versioni mentre il checkpoint scrive quelle nuove.",{"type":24,"tag":37,"props":3073,"children":3074},{},[],{"type":24,"tag":41,"props":3076,"children":3078},{"id":3077},"il-verdetto",[3079],{"type":29,"value":3080},"Il Verdetto",{"type":24,"tag":25,"props":3082,"children":3083},{},[3084],{"type":29,"value":3085},"Per un database di documenti embedded a singolo scrittore, il design a due dizionari di BLite è un punto di compromesso pragmatico. Il rollback è una rimozione da dizionario. Le letture vedono sempre uno stato committed coerente. Il group commit ammortizza la latenza del disco attraverso le transazioni concorrenti. E l'implementazione è abbastanza piccola da leggere in un pomeriggio.",{"type":24,"tag":25,"props":3087,"children":3088},{},[3089],{"type":29,"value":3090},"I limiti — isolamento read committed, scrittori serializzati, checkpoint bloccante — sono reali. Ma per il caso d'uso di gran lunga più comune, \"un processo, accesso sequenziale o leggermente concorrente,\" in pratica non contano.",{"type":24,"tag":25,"props":3092,"children":3093},{},[3094,3096,3105],{"type":29,"value":3095},"Il sorgente completo è su ",{"type":24,"tag":3097,"props":3098,"children":3102},"a",{"href":3099,"rel":3100},"https:\u002F\u002Fgithub.com\u002FEntglDb\u002FBLite",[3101],"nofollow",[3103],{"type":29,"value":3104},"GitHub",{"type":29,"value":404},{"type":24,"tag":3107,"props":3108,"children":3109},"style",{},[3110],{"type":29,"value":3111},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":109,"depth":109,"links":3113},[3114,3115,3116,3117,3119,3121,3122,3123],{"id":43,"depth":109,"text":46},{"id":75,"depth":109,"text":78},{"id":684,"depth":109,"text":687},{"id":1640,"depth":109,"text":3118},"Group Commit: Da _walCache a _walIndex",{"id":2328,"depth":109,"text":3120},"Perché SemaphoreSlim sul WAL Stream",{"id":2554,"depth":109,"text":2557},{"id":2948,"depth":109,"text":2951},{"id":3077,"depth":109,"text":3080},"markdown","content:it:blog:mvcc-transactions-in-blite.md","content","it\u002Fblog\u002Fmvcc-transactions-in-blite.md","it\u002Fblog\u002Fmvcc-transactions-in-blite","md",{"loc":4},1775332618737]