PostgreSQL ضد نمونې: د "مړو" جنګیالیو لښکر

د PostgreSQL د داخلي میکانیزم ځانګړتیاوې دا اجازه ورکوي چې په ځینو حالتونو کې خورا ګړندی وي او په نورو کې "ډیر ګړندی نه وي". نن به موږ د DBMS د کار کولو څرنګوالي او پراختیا کونکي د دې سره څه کوي تر مینځ د شخړې په کلاسیک مثال تمرکز وکړو - تازه کول د MVCC اصول.

څخه لنډه کیسه عالي مقاله:

کله چې یو قطار د UPDATE کمانډ لخوا تعدیل شي، دوه عملیات په حقیقت کې ترسره کیږي: DELETE او INSERT. IN د تار اوسنۍ نسخه xmax د لیږد شمیر سره مساوي ټاکل شوی چې تازه یې ترسره کړی. بیا هغه جوړیږي یوه نوې نسخه ورته کرښه د دې xmin ارزښت د پخوانۍ نسخې xmax ارزښت سره سمون لري.

یو څه وخت وروسته له دې چې دا معامله بشپړه شي، زاړه یا نوې نسخه، پورې اړه لري COMMIT/ROOLBACK، وپیژندل شي "مړ" (مړ ټوپلونه) کله چې تیریږي VACUUM د میز مطابق او پاک شوی.

PostgreSQL ضد نمونې: د "مړو" جنګیالیو لښکر

مګر دا به سمدلاسه نه پیښ شي ، مګر د "مړو" سره ستونزې خورا ګړندي ترلاسه کیدی شي - د تکرار یا تکرار سره. د ریکارډونو ډله ایز تازه کول په یو لوی میز کې، او یو څه وروسته به تاسو د ورته حالت سره مخ شئ 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 او نور منطقي چلونکي د مرستې لپاره:
PostgreSQL ضد نمونې: د "مړو" جنګیالیو لښکر
... او د پیچلو عملیاتو په اړه لږ څه ROW()څرګندونه:
PostgreSQL ضد نمونې: د "مړو" جنګیالیو لښکر

#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

Add a comment