[{"data":1,"prerenderedAt":1003},["ShallowReactive",2],{"blog-\u002Fblog\u002Fsql-isolation-levels-concurrency":3},{"id":4,"title":5,"body":6,"description":989,"difficulty":990,"extension":991,"framework":992,"frameworkSlug":171,"meta":993,"navigation":236,"order":186,"path":994,"qaPath":995,"seo":996,"stem":997,"subtopic":998,"topic":999,"topicSlug":1000,"updated":1001,"__hash__":1002},"blog\u002Fblog\u002Fsql-isolation-levels-concurrency.md","SQL Isolation Levels — Dirty Reads, Phantom Reads, and MVCC",{"type":7,"value":8,"toc":978},"minimark",[9,14,18,21,25,86,90,163,166,273,277,283,380,383,387,390,512,518,522,525,703,707,721,724,747,758,762,765,884,890,952,956,974],[10,11,13],"h2",{"id":12},"the-concurrency-problem","The concurrency problem",[15,16,17],"p",{},"Databases handle many concurrent connections. Without isolation controls, two\ntransactions reading and writing the same rows at the same time can interfere\nin subtle ways — one transaction sees a value that another is about to roll\nback, or a count changes between two reads in the same transaction.",[15,19,20],{},"SQL defines four isolation levels, each preventing a different class of anomaly.",[10,22,24],{"id":23},"the-anomalies-each-level-prevents","The anomalies each level prevents",[26,27,28,41],"table",{},[29,30,31],"thead",{},[32,33,34,38],"tr",{},[35,36,37],"th",{},"Anomaly",[35,39,40],{},"What it is",[42,43,44,56,66,76],"tbody",{},[32,45,46,53],{},[47,48,49],"td",{},[50,51,52],"strong",{},"Dirty read",[47,54,55],{},"Reading another transaction's uncommitted changes",[32,57,58,63],{},[47,59,60],{},[50,61,62],{},"Non-repeatable read",[47,64,65],{},"Re-reading a row and getting a different value because another transaction committed an update between reads",[32,67,68,73],{},[47,69,70],{},[50,71,72],{},"Phantom read",[47,74,75],{},"Re-running a query and getting different rows because another transaction committed an INSERT or DELETE",[32,77,78,83],{},[47,79,80],{},[50,81,82],{},"Lost update",[47,84,85],{},"Two transactions both read a value, both modify it, and one overwrites the other's change",[10,87,89],{"id":88},"the-four-isolation-levels","The four isolation levels",[26,91,92,105],{},[29,93,94],{},[32,95,96,99,101,103],{},[35,97,98],{},"Level",[35,100,52],{},[35,102,62],{},[35,104,72],{},[42,106,107,122,136,150],{},[32,108,109,115,118,120],{},[47,110,111],{},[112,113,114],"code",{},"READ UNCOMMITTED",[47,116,117],{},"Possible",[47,119,117],{},[47,121,117],{},[32,123,124,129,132,134],{},[47,125,126],{},[112,127,128],{},"READ COMMITTED",[47,130,131],{},"Prevented",[47,133,117],{},[47,135,117],{},[32,137,138,143,145,147],{},[47,139,140],{},[112,141,142],{},"REPEATABLE READ",[47,144,131],{},[47,146,131],{},[47,148,149],{},"Possible*",[32,151,152,157,159,161],{},[47,153,154],{},[112,155,156],{},"SERIALIZABLE",[47,158,131],{},[47,160,131],{},[47,162,131],{},[15,164,165],{},"*Postgres's REPEATABLE READ also prevents phantom reads via MVCC.",[167,168,173],"pre",{"className":169,"code":170,"language":171,"meta":172,"style":172},"language-sql shiki shiki-themes github-light github-dark","-- Set isolation level for the current transaction (Postgres \u002F SQL Server)\nBEGIN ISOLATION LEVEL READ COMMITTED;\n-- or\nSET TRANSACTION ISOLATION LEVEL SERIALIZABLE;\n\n-- MySQL\nSET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;\nSTART TRANSACTION;\n","sql","",[112,174,175,184,207,213,231,238,244,265],{"__ignoreMap":172},[176,177,180],"span",{"class":178,"line":179},"line",1,[176,181,183],{"class":182},"sJ8bj","-- Set isolation level for the current transaction (Postgres \u002F SQL Server)\n",[176,185,187,191,194,197,200,203],{"class":178,"line":186},2,[176,188,190],{"class":189},"szBVR","BEGIN",[176,192,193],{"class":189}," ISOLATION",[176,195,196],{"class":189}," LEVEL",[176,198,199],{"class":189}," READ",[176,201,202],{"class":189}," COMMITTED",[176,204,206],{"class":205},"sVt8B",";\n",[176,208,210],{"class":178,"line":209},3,[176,211,212],{"class":182},"-- or\n",[176,214,216,219,222,224,226,229],{"class":178,"line":215},4,[176,217,218],{"class":189},"SET",[176,220,221],{"class":189}," TRANSACTION",[176,223,193],{"class":189},[176,225,196],{"class":189},[176,227,228],{"class":189}," SERIALIZABLE",[176,230,206],{"class":205},[176,232,234],{"class":178,"line":233},5,[176,235,237],{"emptyLinePlaceholder":236},true,"\n",[176,239,241],{"class":178,"line":240},6,[176,242,243],{"class":182},"-- MySQL\n",[176,245,247,249,252,254,256,258,261,263],{"class":178,"line":246},7,[176,248,218],{"class":189},[176,250,251],{"class":189}," SESSION",[176,253,221],{"class":189},[176,255,193],{"class":189},[176,257,196],{"class":189},[176,259,260],{"class":189}," REPEATABLE",[176,262,199],{"class":189},[176,264,206],{"class":205},[176,266,268,271],{"class":178,"line":267},8,[176,269,270],{"class":189},"START TRANSACTION",[176,272,206],{"class":205},[10,274,276],{"id":275},"read-committed-the-practical-default","READ COMMITTED — the practical default",[15,278,279,280,282],{},"Postgres and SQL Server default to ",[112,281,128],{},". Each statement inside the\ntransaction sees only rows committed before that statement started.",[167,284,286],{"className":169,"code":285,"language":171,"meta":172,"style":172},"-- Transaction A: checking inventory before placing an order\nBEGIN;\nSELECT stock_qty FROM product_inventory WHERE product_id = 42;\n-- Returns 5\n\n-- Meanwhile, Transaction B commits: stock_qty = 3 (someone else bought 2 units)\n\nSELECT stock_qty FROM product_inventory WHERE product_id = 42;\n-- Returns 3 — different value in the same transaction (non-repeatable read)\nCOMMIT;\n",[112,287,288,293,299,328,333,337,342,346,366,372],{"__ignoreMap":172},[176,289,290],{"class":178,"line":179},[176,291,292],{"class":182},"-- Transaction A: checking inventory before placing an order\n",[176,294,295,297],{"class":178,"line":186},[176,296,190],{"class":189},[176,298,206],{"class":205},[176,300,301,304,307,310,313,316,319,322,326],{"class":178,"line":209},[176,302,303],{"class":189},"SELECT",[176,305,306],{"class":205}," stock_qty ",[176,308,309],{"class":189},"FROM",[176,311,312],{"class":205}," product_inventory ",[176,314,315],{"class":189},"WHERE",[176,317,318],{"class":205}," product_id ",[176,320,321],{"class":189},"=",[176,323,325],{"class":324},"sj4cs"," 42",[176,327,206],{"class":205},[176,329,330],{"class":178,"line":215},[176,331,332],{"class":182},"-- Returns 5\n",[176,334,335],{"class":178,"line":233},[176,336,237],{"emptyLinePlaceholder":236},[176,338,339],{"class":178,"line":240},[176,340,341],{"class":182},"-- Meanwhile, Transaction B commits: stock_qty = 3 (someone else bought 2 units)\n",[176,343,344],{"class":178,"line":246},[176,345,237],{"emptyLinePlaceholder":236},[176,347,348,350,352,354,356,358,360,362,364],{"class":178,"line":267},[176,349,303],{"class":189},[176,351,306],{"class":205},[176,353,309],{"class":189},[176,355,312],{"class":205},[176,357,315],{"class":189},[176,359,318],{"class":205},[176,361,321],{"class":189},[176,363,325],{"class":324},[176,365,206],{"class":205},[176,367,369],{"class":178,"line":368},9,[176,370,371],{"class":182},"-- Returns 3 — different value in the same transaction (non-repeatable read)\n",[176,373,375,378],{"class":178,"line":374},10,[176,376,377],{"class":189},"COMMIT",[176,379,206],{"class":205},[15,381,382],{},"This is acceptable for most operations but dangerous for \"read-then-write\"\npatterns where both reads must see the same value.",[10,384,386],{"id":385},"repeatable-read-stable-snapshots","REPEATABLE READ — stable snapshots",[15,388,389],{},"Each transaction works from a snapshot taken at its first read. Subsequent reads\nof the same row return the same value, regardless of what other transactions\ncommit.",[167,391,393],{"className":169,"code":392,"language":171,"meta":172,"style":172},"-- Transaction A: generating a financial report\nBEGIN ISOLATION LEVEL REPEATABLE READ;\n\nSELECT SUM(total_amount) FROM orders WHERE created_at::DATE = '2026-06-20';\n-- Returns 12,450.00\n\n-- Transaction B commits new orders during this time\n\nSELECT COUNT(*) FROM orders WHERE created_at::DATE = '2026-06-20';\n-- Still reflects the same snapshot — consistent report\nCOMMIT;\n",[112,394,395,400,414,418,450,455,459,464,468,500,505],{"__ignoreMap":172},[176,396,397],{"class":178,"line":179},[176,398,399],{"class":182},"-- Transaction A: generating a financial report\n",[176,401,402,404,406,408,410,412],{"class":178,"line":186},[176,403,190],{"class":189},[176,405,193],{"class":189},[176,407,196],{"class":189},[176,409,260],{"class":189},[176,411,199],{"class":189},[176,413,206],{"class":205},[176,415,416],{"class":178,"line":209},[176,417,237],{"emptyLinePlaceholder":236},[176,419,420,422,425,428,430,433,435,438,441,444,448],{"class":178,"line":215},[176,421,303],{"class":189},[176,423,424],{"class":324}," SUM",[176,426,427],{"class":205},"(total_amount) ",[176,429,309],{"class":189},[176,431,432],{"class":205}," orders ",[176,434,315],{"class":189},[176,436,437],{"class":205}," created_at::",[176,439,440],{"class":189},"DATE",[176,442,443],{"class":189}," =",[176,445,447],{"class":446},"sZZnC"," '2026-06-20'",[176,449,206],{"class":205},[176,451,452],{"class":178,"line":233},[176,453,454],{"class":182},"-- Returns 12,450.00\n",[176,456,457],{"class":178,"line":240},[176,458,237],{"emptyLinePlaceholder":236},[176,460,461],{"class":178,"line":246},[176,462,463],{"class":182},"-- Transaction B commits new orders during this time\n",[176,465,466],{"class":178,"line":267},[176,467,237],{"emptyLinePlaceholder":236},[176,469,470,472,475,478,481,484,486,488,490,492,494,496,498],{"class":178,"line":368},[176,471,303],{"class":189},[176,473,474],{"class":324}," COUNT",[176,476,477],{"class":205},"(",[176,479,480],{"class":189},"*",[176,482,483],{"class":205},") ",[176,485,309],{"class":189},[176,487,432],{"class":205},[176,489,315],{"class":189},[176,491,437],{"class":205},[176,493,440],{"class":189},[176,495,443],{"class":189},[176,497,447],{"class":446},[176,499,206],{"class":205},[176,501,502],{"class":178,"line":374},[176,503,504],{"class":182},"-- Still reflects the same snapshot — consistent report\n",[176,506,508,510],{"class":178,"line":507},11,[176,509,377],{"class":189},[176,511,206],{"class":205},[15,513,514,515,517],{},"MySQL's default isolation level is ",[112,516,142],{},".",[10,519,521],{"id":520},"serializable-full-correctness-higher-cost","SERIALIZABLE — full correctness, higher cost",[15,523,524],{},"Transactions execute as if they ran one at a time (serially). The database\ndetects any read\u002Fwrite conflicts and aborts one of the transactions — the\napplication must retry.",[167,526,528],{"className":169,"code":527,"language":171,"meta":172,"style":172},"-- Booking system: prevent double-booking a conference room\nBEGIN ISOLATION LEVEL SERIALIZABLE;\n\nSELECT COUNT(*) FROM bookings\nWHERE room_id = 7\n  AND start_time \u003C '2026-06-25 15:00'\n  AND end_time   > '2026-06-25 14:00';\n-- Returns 0 — room appears free\n\n-- Concurrent transaction B runs the same check and also gets 0\n\n-- Both insert a booking:\nINSERT INTO bookings (room_id, start_time, end_time, user_id)\nVALUES (7, '2026-06-25 14:00', '2026-06-25 15:00', 44);\n\nCOMMIT;\n-- One of the two transactions gets:\n-- ERROR: could not serialize access due to concurrent update\n-- The application retries the failed transaction\n",[112,529,530,535,547,551,568,580,594,609,614,618,623,627,633,642,673,678,685,691,697],{"__ignoreMap":172},[176,531,532],{"class":178,"line":179},[176,533,534],{"class":182},"-- Booking system: prevent double-booking a conference room\n",[176,536,537,539,541,543,545],{"class":178,"line":186},[176,538,190],{"class":189},[176,540,193],{"class":189},[176,542,196],{"class":189},[176,544,228],{"class":189},[176,546,206],{"class":205},[176,548,549],{"class":178,"line":209},[176,550,237],{"emptyLinePlaceholder":236},[176,552,553,555,557,559,561,563,565],{"class":178,"line":215},[176,554,303],{"class":189},[176,556,474],{"class":324},[176,558,477],{"class":205},[176,560,480],{"class":189},[176,562,483],{"class":205},[176,564,309],{"class":189},[176,566,567],{"class":205}," bookings\n",[176,569,570,572,575,577],{"class":178,"line":233},[176,571,315],{"class":189},[176,573,574],{"class":205}," room_id ",[176,576,321],{"class":189},[176,578,579],{"class":324}," 7\n",[176,581,582,585,588,591],{"class":178,"line":240},[176,583,584],{"class":189},"  AND",[176,586,587],{"class":205}," start_time ",[176,589,590],{"class":189},"\u003C",[176,592,593],{"class":446}," '2026-06-25 15:00'\n",[176,595,596,598,601,604,607],{"class":178,"line":246},[176,597,584],{"class":189},[176,599,600],{"class":205}," end_time   ",[176,602,603],{"class":189},">",[176,605,606],{"class":446}," '2026-06-25 14:00'",[176,608,206],{"class":205},[176,610,611],{"class":178,"line":267},[176,612,613],{"class":182},"-- Returns 0 — room appears free\n",[176,615,616],{"class":178,"line":368},[176,617,237],{"emptyLinePlaceholder":236},[176,619,620],{"class":178,"line":374},[176,621,622],{"class":182},"-- Concurrent transaction B runs the same check and also gets 0\n",[176,624,625],{"class":178,"line":507},[176,626,237],{"emptyLinePlaceholder":236},[176,628,630],{"class":178,"line":629},12,[176,631,632],{"class":182},"-- Both insert a booking:\n",[176,634,636,639],{"class":178,"line":635},13,[176,637,638],{"class":189},"INSERT INTO",[176,640,641],{"class":205}," bookings (room_id, start_time, end_time, user_id)\n",[176,643,645,648,651,654,657,660,662,665,667,670],{"class":178,"line":644},14,[176,646,647],{"class":189},"VALUES",[176,649,650],{"class":205}," (",[176,652,653],{"class":324},"7",[176,655,656],{"class":205},", ",[176,658,659],{"class":446},"'2026-06-25 14:00'",[176,661,656],{"class":205},[176,663,664],{"class":446},"'2026-06-25 15:00'",[176,666,656],{"class":205},[176,668,669],{"class":324},"44",[176,671,672],{"class":205},");\n",[176,674,676],{"class":178,"line":675},15,[176,677,237],{"emptyLinePlaceholder":236},[176,679,681,683],{"class":178,"line":680},16,[176,682,377],{"class":189},[176,684,206],{"class":205},[176,686,688],{"class":178,"line":687},17,[176,689,690],{"class":182},"-- One of the two transactions gets:\n",[176,692,694],{"class":178,"line":693},18,[176,695,696],{"class":182},"-- ERROR: could not serialize access due to concurrent update\n",[176,698,700],{"class":178,"line":699},19,[176,701,702],{"class":182},"-- The application retries the failed transaction\n",[10,704,706],{"id":705},"mvcc-how-postgres-implements-isolation","MVCC — how Postgres implements isolation",[15,708,709,710,713,714,656,717,720],{},"Postgres uses ",[50,711,712],{},"Multi-Version Concurrency Control (MVCC)",". Instead of locking\nrows for reads, every write creates a new row version with transaction ID\ntimestamps (",[112,715,716],{},"xmin",[112,718,719],{},"xmax","). Readers get a consistent snapshot by ignoring row\nversions committed after their snapshot began.",[15,722,723],{},"This means:",[725,726,727,734,740],"ul",{},[728,729,730,733],"li",{},[50,731,732],{},"Readers never block writers"," (no read locks).",[728,735,736,739],{},[50,737,738],{},"Writers never block readers"," (old row versions remain readable).",[728,741,742,743,746],{},"Only ",[50,744,745],{},"writer-writer conflicts"," require locks.",[15,748,749,750,753,754,757],{},"The cost: old row versions accumulate (called ",[50,751,752],{},"dead tuples",") until ",[112,755,756],{},"VACUUM","\ncleans them up. Tables with heavy UPDATE traffic need regular vacuuming.",[10,759,761],{"id":760},"select-for-update-explicit-row-locking","SELECT FOR UPDATE — explicit row locking",[15,763,764],{},"When a \"read then write\" pattern needs protection against concurrent updates,\nlock the row at read time:",[167,766,768],{"className":169,"code":767,"language":171,"meta":172,"style":172},"BEGIN;\n\n-- Lock the inventory row so no other transaction can update it until we commit\nSELECT stock_qty\nFROM   product_inventory\nWHERE  product_id = 42\nFOR UPDATE;                -- acquires an exclusive row lock\n\n-- Now safely decrement\nUPDATE product_inventory\nSET stock_qty = stock_qty - 2\nWHERE product_id = 42;\n\nCOMMIT;  -- lock released\n",[112,769,770,776,780,785,792,799,811,825,829,834,842,858,870,874],{"__ignoreMap":172},[176,771,772,774],{"class":178,"line":179},[176,773,190],{"class":189},[176,775,206],{"class":205},[176,777,778],{"class":178,"line":186},[176,779,237],{"emptyLinePlaceholder":236},[176,781,782],{"class":178,"line":209},[176,783,784],{"class":182},"-- Lock the inventory row so no other transaction can update it until we commit\n",[176,786,787,789],{"class":178,"line":215},[176,788,303],{"class":189},[176,790,791],{"class":205}," stock_qty\n",[176,793,794,796],{"class":178,"line":233},[176,795,309],{"class":189},[176,797,798],{"class":205},"   product_inventory\n",[176,800,801,803,806,808],{"class":178,"line":240},[176,802,315],{"class":189},[176,804,805],{"class":205},"  product_id ",[176,807,321],{"class":189},[176,809,810],{"class":324}," 42\n",[176,812,813,816,819,822],{"class":178,"line":246},[176,814,815],{"class":189},"FOR",[176,817,818],{"class":189}," UPDATE",[176,820,821],{"class":205},";                ",[176,823,824],{"class":182},"-- acquires an exclusive row lock\n",[176,826,827],{"class":178,"line":267},[176,828,237],{"emptyLinePlaceholder":236},[176,830,831],{"class":178,"line":368},[176,832,833],{"class":182},"-- Now safely decrement\n",[176,835,836,839],{"class":178,"line":374},[176,837,838],{"class":189},"UPDATE",[176,840,841],{"class":205}," product_inventory\n",[176,843,844,846,848,850,852,855],{"class":178,"line":507},[176,845,218],{"class":189},[176,847,306],{"class":205},[176,849,321],{"class":189},[176,851,306],{"class":205},[176,853,854],{"class":189},"-",[176,856,857],{"class":324}," 2\n",[176,859,860,862,864,866,868],{"class":178,"line":629},[176,861,315],{"class":189},[176,863,318],{"class":205},[176,865,321],{"class":189},[176,867,325],{"class":324},[176,869,206],{"class":205},[176,871,872],{"class":178,"line":635},[176,873,237],{"emptyLinePlaceholder":236},[176,875,876,878,881],{"class":178,"line":644},[176,877,377],{"class":189},[176,879,880],{"class":205},";  ",[176,882,883],{"class":182},"-- lock released\n",[15,885,886,889],{},[112,887,888],{},"FOR UPDATE SKIP LOCKED"," is useful for job queues — workers pick up tasks\nwithout waiting for each other:",[167,891,893],{"className":169,"code":892,"language":171,"meta":172,"style":172},"-- Worker picks the next unclaimed job, skipping any locked by other workers\nSELECT id, payload FROM job_queue\nWHERE status = 'pending'\nORDER BY created_at\nLIMIT 1\nFOR UPDATE SKIP LOCKED;\n",[112,894,895,900,912,924,932,940],{"__ignoreMap":172},[176,896,897],{"class":178,"line":179},[176,898,899],{"class":182},"-- Worker picks the next unclaimed job, skipping any locked by other workers\n",[176,901,902,904,907,909],{"class":178,"line":186},[176,903,303],{"class":189},[176,905,906],{"class":205}," id, payload ",[176,908,309],{"class":189},[176,910,911],{"class":205}," job_queue\n",[176,913,914,916,919,921],{"class":178,"line":209},[176,915,315],{"class":189},[176,917,918],{"class":189}," status",[176,920,443],{"class":189},[176,922,923],{"class":446}," 'pending'\n",[176,925,926,929],{"class":178,"line":215},[176,927,928],{"class":189},"ORDER BY",[176,930,931],{"class":205}," created_at\n",[176,933,934,937],{"class":178,"line":233},[176,935,936],{"class":189},"LIMIT",[176,938,939],{"class":324}," 1\n",[176,941,942,944,946,949],{"class":178,"line":240},[176,943,815],{"class":189},[176,945,818],{"class":189},[176,947,948],{"class":189}," SKIP",[176,950,951],{"class":205}," LOCKED;\n",[10,953,955],{"id":954},"recap","Recap",[15,957,958,959,961,962,964,965,967,968,971,972,517],{},"Default to ",[112,960,128],{}," for most OLTP work. Upgrade to ",[112,963,142],{},"\nfor long-running reports or batch jobs where consistent snapshots matter. Use\n",[112,966,156],{}," only for logic that requires complete correctness (inventory,\nseat booking, financial ledgers) — and always implement retry logic, because\nserialization failures are expected and normal. Use ",[112,969,970],{},"SELECT FOR UPDATE"," for\nexplicit row locks in read-then-write patterns. Understand MVCC: readers and\nwriters do not block each other in Postgres, but dead tuples accumulate and must\nbe cleaned up by ",[112,973,756],{},[975,976,977],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}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);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":172,"searchDepth":186,"depth":186,"links":979},[980,981,982,983,984,985,986,987,988],{"id":12,"depth":186,"text":13},{"id":23,"depth":186,"text":24},{"id":88,"depth":186,"text":89},{"id":275,"depth":186,"text":276},{"id":385,"depth":186,"text":386},{"id":520,"depth":186,"text":521},{"id":705,"depth":186,"text":706},{"id":760,"depth":186,"text":761},{"id":954,"depth":186,"text":955},"SQL isolation levels explained — READ COMMITTED, REPEATABLE READ, SERIALIZABLE, dirty reads, phantom reads, lost updates, MVCC, and SELECT FOR UPDATE.","hard","md","SQL",{},"\u002Fblog\u002Fsql-isolation-levels-concurrency","\u002Fsql\u002Ftransactions\u002Fisolation-concurrency",{"title":5,"description":989},"blog\u002Fsql-isolation-levels-concurrency","Isolation & Concurrency","Transactions","transactions","2026-06-20","xWn6o2UqTapSQrZbSY0wcUY9XW-E8YufuczBpPX5N5Y",1782244088533]