د PostgreSQL د داخلي میکانیزم ځانګړتیاوې دا اجازه ورکوي چې په ځینو حالتونو کې خورا ګړندی وي او په نورو کې "ډیر ګړندی نه وي". نن به موږ د DBMS د کار کولو څرنګوالي او پراختیا کونکي د دې سره څه کوي تر مینځ د شخړې په کلاسیک مثال تمرکز وکړو - تازه کول د MVCC اصول.
څخه لنډه کیسه
کله چې یو قطار د UPDATE کمانډ لخوا تعدیل شي، دوه عملیات په حقیقت کې ترسره کیږي: DELETE او INSERT. IN د تار اوسنۍ نسخه xmax د لیږد شمیر سره مساوي ټاکل شوی چې تازه یې ترسره کړی. بیا هغه جوړیږي یوه نوې نسخه ورته کرښه د دې xmin ارزښت د پخوانۍ نسخې xmax ارزښت سره سمون لري.
یو څه وخت وروسته له دې چې دا معامله بشپړه شي، زاړه یا نوې نسخه، پورې اړه لري COMMIT/ROOLBACK
، وپیژندل شي "مړ" (مړ ټوپلونه) کله چې تیریږي VACUUM
د میز مطابق او پاک شوی.
مګر دا به سمدلاسه نه پیښ شي ، مګر د "مړو" سره ستونزې خورا ګړندي ترلاسه کیدی شي - د تکرار یا تکرار سره.
#1: زه خوښوم چې دا حرکت وکړم
راځئ چې ووایو ستاسو طریقه د سوداګرۍ منطق باندې کار کوي، او ناڅاپه پوه شو چې دا به اړین وي چې په ځینې ریکارډ کې د ایکس ساحه تازه کړي:
UPDATE tbl SET X = <newX> WHERE pk = $1;
بیا، لکه څنګه چې اجرا کول پرمختګ کوي، دا معلومه شوه چې د Y ساحه باید تازه شي:
UPDATE tbl SET Y = <newY> WHERE pk = $1;
... او بیا هم Z - ولې په لنډیو وخت ضایع کوئ؟
UPDATE tbl SET Z = <newZ> WHERE pk = $1;
د دې ریکارډ څو نسخې اوس موږ په ډیټابیس کې لرو؟ هو، 4 ټوټې! له دې څخه، یو اړوند دی، او 3 باید ستاسو وروسته د [آټو] ویکیوم لخوا پاک شي.
داسې مه کوه! کارول په یوه غوښتنه کې ټولې ساحې تازه کول - نږدې تل د میتود منطق په دې ډول بدلیدلی شي:
UPDATE tbl SET X = <newX>, Y = <newY>, Z = <newZ> WHERE pk = $1;
#2: له IS توپیر څخه کار واخلئ، لوقا!
نو، تاسو لاهم غوښتل
UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2;
په دې فورمه کې یوه غوښتنه ډیری وختونه پیښیږي او نږدې تل د خالي نوي ساحې ډکولو لپاره نه وي ، مګر په ډیټا کې د ځینې غلطیو سمولو لپاره. په ورته وخت کې، هغې پخپله د موجوده معلوماتو درستیت په پام کې نه نیول کیږي - خو بې ګټې! دا دی، ریکارډ بیا لیکل شوی، حتی که دا په ریښتیا هغه څه ولري چې غوښتل یې - مګر ولې؟ راځئ چې دا سم کړو:
UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2 AND X IS DISTINCT FROM <newX>;
ډیری خلک د داسې عالي آپریټر له شتون څخه خبر ندي ، نو دلته د غلا شیټ دی IS DISTINCT FROM
او نور منطقي چلونکي د مرستې لپاره:
... او د پیچلو عملیاتو په اړه لږ څه ROW()
څرګندونه:
#3: زه خپل خواږه د بندولو په واسطه پیژنم
په لاره اچول کیږي دوه ورته موازي پروسې، چې هر یو یې هڅه کوي دا ننوتنه په نښه کړي چې دا "پرمختګ" دی:
UPDATE tbl SET processing = TRUE WHERE pk = $1;
حتی که دا پروسې واقعیا د یو بل څخه خپلواک شیان ترسره کړي ، مګر په ورته ID کې ، دوهم پیرودونکی به پدې غوښتنې باندې "لاک" وي تر هغه چې لومړۍ معامله بشپړه شوې نه وي.
حل # 1: دنده مخکینی ته راټیټه شوې
راځئ چې یو ځل بیا اضافه کړو IS DISTINCT FROM
:
UPDATE tbl SET processing = TRUE WHERE pk = $1 AND processing IS DISTINCT FROM TRUE;
په دې فورمه کې، دویمه غوښتنه به په ساده ډول په ډیټابیس کې هیڅ شی بدل نه کړي، هرڅه لا دمخه دي لکه څنګه چې باید وي - له همدې امله، بلاک کول به واقع نشي. بیا، موږ په پلي شوي الګوریتم کې د ریکارډ "نه موندلو" حقیقت پروسس کوو.
حل # 2: مشورتي قفلونه
د جلا مقالې لپاره یوه لویه موضوع، په کوم کې چې تاسو یې لوستلی شئ
حل # 3: احمقانه زنګونه
مګر دا واقعیا هغه څه دي چې باید تاسو سره پیښ شي په ورته وخت کې د ورته ریکارډ سره کار؟ یا ایا تاسو د پیرودونکي اړخ کې د سوداګرۍ منطق ته زنګ وهلو لپاره د الګوریتم سره ګډوډ یاست ، د مثال په توګه؟ او که تاسو په دې اړه فکر کوئ؟ ...
سرچینه: www.habr.com