Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Բրյուս Մոմջյանի 2020 թվականի «Բացելով Պոստգրեսի կողպեքի մենեջերի» զրույցի սղագրությունը։

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

(Ծանոթագրություն. Սլայդներից բոլոր SQL հարցումները կարելի է ստանալ այս հղումից. http://momjian.us/main/writings/pgsql/locking.sql)

Բարեւ Ձեզ! Հիանալի է կրկին այստեղ լինել Ռուսաստանում: Ցավում եմ, որ չկարողացա գալ անցյալ տարի, բայց այս տարի ես ու Իվանը մեծ ծրագրեր ունենք։ Հուսով եմ, որ այստեղ շատ ավելի հաճախ կլինեմ: Ես սիրում եմ գալ Ռուսաստան. Ես կայցելեմ Տյումեն, Տվեր: Շատ ուրախ եմ, որ կկարողանամ այցելել այս քաղաքները։

Ես Բրյուս Մոմջյանն եմ: Ես աշխատում եմ EnterpriseDB-ում և աշխատում եմ Postgres-ի հետ ավելի քան 23 տարի: Ես ապրում եմ Ֆիլադելֆիա, ԱՄՆ: Ես ճանապարհորդում եմ տարեկան մոտ 90 օր: Եվ ես մասնակցում եմ մոտ 40 կոնֆերանսի: Իմ Վեբ կայք, որը պարունակում է սլայդներ, որոնք ես հիմա ցույց կտամ ձեզ: Հետևաբար, համաժողովից հետո դրանք կարող եք ներբեռնել իմ անձնական կայքից: Այն նաև պարունակում է մոտ 30 շնորհանդեսներ: Կան նաև տեսանյութեր և մեծ թվով բլոգային գրառումներ՝ ավելի քան 500: Սա բավականին տեղեկատվական ռեսուրս է: Եվ եթե ձեզ հետաքրքրում է այս նյութը, ապա ես ձեզ հրավիրում եմ օգտագործել այն:

Ես եղել եմ ուսուցիչ, պրոֆեսոր, նախքան «Պոստգրես»-ի հետ աշխատելը: Եվ ես շատ ուրախ եմ, որ այժմ կկարողանամ պատմել ձեզ այն, ինչ պատրաստվում եմ ձեզ ասել: Սա իմ ամենահետաքրքիր շնորհանդեսներից մեկն է։ Եվ այս շնորհանդեսը պարունակում է 110 սլայդ: Մենք կսկսենք խոսել պարզ բաներից, և վերջում զեկույցն ավելի ու ավելի բարդ է դառնալու և բավականին բարդանալու է։

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Սա բավականին տհաճ խոսակցություն է։ Արգելափակումը ամենահայտնի թեման չէ: Մենք ուզում ենք, որ սա ինչ-որ տեղ վերանա: Դա նման է ատամնաբույժի գնալուն:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

  1. Կողպելը խնդիր է շատ մարդկանց համար, ովքեր աշխատում են տվյալների շտեմարաններում և ունեն միաժամանակ մի քանի գործընթացներ: Նրանք արգելափակման կարիք ունեն։ Այսինքն՝ այսօր ես ձեզ հիմնական գիտելիքներ կտամ արգելափակման վերաբերյալ։
  2. Գործարքի ID-ներ. Սա ներկայացման բավականին ձանձրալի հատված է, բայց դրանք պետք է հասկանալ:
  3. Հաջորդիվ կխոսենք արգելափակման տեսակների մասին։ Սա բավականին մեխանիկական մաս է:
  4. Իսկ ստորև մենք կասենք արգելափակման մի քանի օրինակ։ Եվ դա բավականին դժվար կլինի հասկանալ։

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եկեք խոսենք արգելափակման մասին:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Մեր տերմինաբանությունը բավականին բարդ է։ Ձեզանից քանի՞սը գիտեն, թե որտեղից է գալիս այս հատվածը: Երկու մարդ. Սա Colossal Cave Adventure կոչվող խաղից է: Կարծում եմ, 80-ականներին տեքստային համակարգչային խաղ էր: Այնտեղ պետք է մտնեիր քարանձավ, լաբիրինթոս, և տեքստը փոխվեց, բայց բովանդակությունը մոտավորապես նույնն էր ամեն անգամ։ Այդպես եմ հիշում այս խաղը։

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ ահա մենք տեսնում ենք Oracle-ից մեզ հասած կողպեքների անվանումը։ Մենք օգտագործում ենք դրանք:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Այստեղ մենք տեսնում ենք տերմիններ, որոնք շփոթեցնում են ինձ: Օրինակ՝ SHARE UPDATE ECXLUSIVE: Հաջորդ ԿԻՍՎԵԼ RAW EXLUSIVE. Անկեղծ ասած, այս անուններն այնքան էլ պարզ չեն։ Մենք կփորձենք դրանք ավելի մանրամասն դիտարկել: Ոմանք պարունակում են «կիսել» բառը, որը նշանակում է առանձնացնել: Որոշները պարունակում են «բացառիկ» բառը: Ոմանք պարունակում են այս երկու բառերը: Ես կցանկանայի սկսել նրանից, թե ինչպես են աշխատում այս կողպեքները:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ շատ կարևոր է նաև «մուտք» բառը։ Իսկ «շարք» բառերը լար են: Այսինքն՝ մուտքի բաշխում, տողերի բաշխում։

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Մեկ այլ խնդիր, որը պետք է հասկանալ Պոստգրեսում, որը ես, ցավոք, չեմ կարողանա լուսաբանել իմ ելույթում, MVCC-ն է: Ես այս թեմայով առանձին ներկայացում ունեմ իմ կայքում: Եվ եթե կարծում եք, որ այս ներկայացումը դժվար է, MVCC-ն, հավանաբար, իմ ամենադժվարն է: Իսկ եթե հետաքրքրեց, կարող եք դիտել կայքում։ Տեսանյութը կարող եք դիտել։

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Մեկ այլ բան, որ մենք պետք է հասկանանք, գործարքի նույնացուցիչներն են: Շատ գործարքներ չեն կարող աշխատել առանց եզակի նույնացուցիչների: Եվ ահա մենք ունենք բացատրություն, թե ինչ է գործարքը։ Postgres-ն ունի գործարքների համարակալման երկու համակարգ: Ես գիտեմ, որ սա այնքան էլ գեղեցիկ լուծում չէ:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Նկատի ունեցեք նաև, որ սլայդները բավականին դժվար կլինի հասկանալ, ուստի կարմիրով ընդգծվածն այն է, ինչին պետք է ուշադրություն դարձնել:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

http://momjian.us/main/writings/pgsql/locking.sql

Եկեք տեսնենք. Գործարքի համարը նշվում է կարմիրով: Այստեղ ցուցադրված է SELECT pg_back ֆունկցիան: Այն վերադարձնում է իմ գործարքը և գործարքի ID-ն:

Եվս մեկ բան, եթե ձեզ դուր է գալիս այս ներկայացումը և ցանկանում եք այն գործարկել ձեր տվյալների բազայում, ապա կարող եք անցնել այս հղումը վարդագույն գույնով և ներբեռնել SQL-ն այս ներկայացման համար: Եվ դուք կարող եք պարզապես գործարկել այն ձեր PSQL-ում, և ամբողջ ներկայացումը անմիջապես կհայտնվի ձեր էկրանին: Այն ծաղիկներ չի պարունակի, բայց գոնե մենք կարող ենք դա տեսնել:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Այս դեպքում մենք տեսնում ենք գործարքի ID-ն: Սա այն համարն է, որը մենք նրան հանձնարարել ենք: Իսկ Postgres-ում կա գործարքի ID-ի մեկ այլ տեսակ, որը կոչվում է վիրտուալ գործարքի ID

Եվ մենք պետք է սա հասկանանք. Սա շատ կարևոր է, այլապես մենք չենք կարողանա հասկանալ Պոստգրեսում փակվելը։

Վիրտուալ գործարքի ID-ն գործարքի նույնացուցիչ է, որը մշտական ​​արժեքներ չի պարունակում: Օրինակ, եթե ես գործարկեմ SELECT հրամանը, ապա ես ամենայն հավանականությամբ չեմ փոխի տվյալների բազան, ես ոչինչ չեմ արգելափակի: Այսպիսով, երբ մենք գործարկում ենք պարզ SELECT, մենք այդ գործարքին մշտական ​​ID չենք տալիս: Այնտեղ մենք նրան տալիս ենք միայն վիրտուալ ID:

Եվ սա բարելավում է Postgres-ի աշխատանքը, բարելավում է մաքրման հնարավորությունները, ուստի վիրտուալ գործարքի ID-ն բաղկացած է երկու թվից: Շեղից առաջ առաջին համարը հետնամասի ID-ն է: Իսկ աջ կողմում մենք տեսնում ենք ընդամենը հաշվիչը:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Հետևաբար, եթե ես հարցում կատարեմ, այն ասում է, որ backend ID-ն 2 է:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ եթե ես կատարում եմ նման գործարքների շարք, ապա մենք տեսնում ենք, որ հաշվիչը մեծանում է ամեն անգամ, երբ հարցում եմ անում: Օրինակ, երբ ես գործարկում եմ հարցումը 2/10, 2/11, 2/12 և այլն:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Հիշեք, որ այստեղ կա երկու սյունակ: Ձախ կողմում մենք տեսնում ենք վիրտուալ գործարքի ID – 2/12: Իսկ աջ կողմում մենք ունենք մշտական ​​գործարքի ID: Եվ այս դաշտը դատարկ է: Եվ այս գործարքը չի փոփոխում տվյալների բազան: Այսպիսով, ես դրան մշտական ​​գործարքի ID չեմ տալիս:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Հենց որ ես գործարկում եմ վերլուծության հրամանը ((ANALYZE)), նույն հարցումն ինձ տալիս է մշտական ​​գործարքի ID: Տեսեք, թե ինչպես է դա փոխվել մեզ համար: Ես նախկինում չունեի այս ID-ն, բայց հիմա ունեմ այն:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Այսպիսով, ահա ևս մեկ խնդրանք, ևս մեկ գործարք: Վիրտուալ գործարքի համարը 2/13 է: Եվ եթե ես խնդրեմ մշտական ​​գործարքի ID, ապա երբ ես գործարկեմ հարցումը, ես այն կստանամ:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Այսպիսով, ևս մեկ անգամ: Մենք ունենք վիրտուալ գործարքի ID և մշտական ​​գործարքի ID: Պարզապես հասկացեք այս կետը, որպեսզի հասկանաք Պոստգրեսի պահվածքը:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Մենք անցնում ենք երրորդ հատվածին: Այստեղ մենք պարզապես կանցնենք Պոստգրեսի տարբեր տեսակի կողպեքների միջով: Դա այնքան էլ հետաքրքիր չէ: Վերջին բաժինը շատ ավելի հետաքրքիր կլինի։ Բայց մենք պետք է հաշվի առնենք հիմնական բաները, քանի որ հակառակ դեպքում մենք չենք հասկանա, թե ինչ կլինի հետո։

Մենք կանցնենք այս բաժինը, մենք կանդրադառնանք կողպեքի յուրաքանչյուր տեսակին: Եվ ես ձեզ ցույց կտամ օրինակներ, թե ինչպես են դրանք տեղադրվում, ինչպես են աշխատում, ես ձեզ ցույց կտամ որոշ հարցումներ, որոնք կարող եք օգտագործել՝ տեսնելու, թե ինչպես է աշխատում կողպումը Postgres-ում:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Հարցում ստեղծելու և տեսնելու, թե ինչ է կատարվում Postgres-ում, մենք պետք է հարցումը թողարկենք համակարգի տեսքում: Այս դեպքում pg_lock-ը ընդգծված է կարմիրով: Pg_lock-ը համակարգի աղյուսակ է, որը ցույց է տալիս, թե ինչ կողպեքներ են ներկայումս օգտագործվում Postgres-ում:

Այնուամենայնիվ, ինձ համար շատ դժվար է ինքնուրույն ցույց տալ ձեզ pg_lock, քանի որ այն բավականին բարդ է: Այսպիսով, ես ստեղծեցի տեսք, որը ցույց է տալիս pg_locks: Եվ դա նաև որոշակի աշխատանք է կատարում ինձ համար, որը թույլ է տալիս ինձ ավելի լավ հասկանալ: Այսինքն, այն բացառում է իմ կողպեքները, իմ սեփական նիստը և այլն: Դա պարզապես ստանդարտ SQL է և թույլ է տալիս ավելի լավ ցույց տալ ձեզ, թե ինչ է կատարվում:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Մյուս խնդիրն այն է, որ այս տեսակետը շատ լայն է, ուստի ես պետք է ստեղծեմ երկրորդը՝ lockview2:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան Եվ դա ինձ ավելի շատ սյունակներ է ցույց տալիս աղյուսակից: Եվ ևս մեկը, որը ցույց է տալիս ինձ մնացած սյունակները: Սա բավականին բարդ է, ուստի ես փորձեցի հնարավորինս պարզ ներկայացնել:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Այսպիսով, մենք ստեղծեցինք աղյուսակ, որը կոչվում է Lockdemo: Եվ մենք այնտեղ ստեղծեցինք մեկ տող: Սա մեր օրինակելի աղյուսակն է: Եվ մենք կստեղծենք բաժիններ միայն ձեզ ցույց տալու կողպեքների օրինակներ:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Այսպիսով, մեկ տող, մեկ սյունակ: Կողպեքի առաջին տեսակը կոչվում է ACCESS SHARE: Սա ամենաքիչ սահմանափակող արգելափակումն է: Սա նշանակում է, որ այն գործնականում չի հակասում այլ կողպեքների հետ:

Եվ եթե մենք ցանկանում ենք հստակորեն սահմանել կողպեք, մենք գործարկում ենք «lock table» հրամանը: Եվ դա ակնհայտորեն կարգելափակվի, այսինքն՝ ACCESS SHARE ռեժիմում մենք գործարկում ենք կողպեքի աղյուսակը: Եվ եթե ես գործարկում եմ PSQL-ը հետին պլանում, ապա ես սկսում եմ երկրորդ նիստը իմ առաջին նիստից այսպես. Այսինքն՝ ի՞նչ եմ անելու այստեղ։ Ես գնում եմ մեկ այլ նիստի և ասում «ցույց տուր ինձ lockview այս հարցման համար»: Եվ ահա ես ունեմ AccessShareLock այս աղյուսակում: Սա հենց այն է, ինչ ես խնդրեցի: Եվ ասում է, որ բլոկը նշանակված է։ Շատ պարզ.

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Ավելին, եթե նայենք երկրորդ սյունակին, ապա այնտեղ ոչինչ չկա։ Նրանք դատարկ են։

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ եթե ես գործարկեմ «SELECT» հրամանը, ապա սա AccessShareLock պահանջելու անուղղակի (բացահայտ) ձևն է: Այսպիսով, ես թողարկում եմ իմ աղյուսակը և գործարկում եմ հարցումը, և հարցումը վերադարձնում է մի քանի տող: Իսկ տողերից մեկում տեսնում ենք AccessShareLock-ը։ Այսպիսով, SELECT-ը սեղանի վրա կանչում է AccessShareLock-ը: Եվ դա գործնականում ոչ մի բանի հետ չի հակասում, քանի որ դա ցածր մակարդակի կողպեք է:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Իսկ եթե ես գործարկեմ SELECT և ունենամ երեք տարբեր աղյուսակներ: Նախկինում ես աշխատում էի միայն մեկ աղյուսակ, հիմա աշխատում եմ երեքը՝ pg_class, pg_namespace և pg_attribute:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ հիմա, երբ նայում եմ հարցումը, տեսնում եմ 9 AccessShareLocks երեք աղյուսակներում: Ինչո՞ւ։ Երեք աղյուսակներ ընդգծված են կապույտով՝ pg_attribute, pg_class, pg_namespace: Բայց դուք կարող եք նաև տեսնել, որ բոլոր ինդեքսները, որոնք սահմանված են այս աղյուսակների միջոցով, նույնպես ունեն AccessShareLock:

Եվ սա կողպեք է, որը գործնականում չի հակասում ուրիշների հետ: Եվ այն ամենը, ինչ անում է, պարզապես խանգարում է մեզ վերակայել աղյուսակը, մինչ մենք ընտրում ենք այն: Դա իմաստ ունի: Այսինքն, եթե մենք ընտրում ենք աղյուսակ, այն անհետանում է այդ պահին, ապա սա սխալ է, ուրեմն AccessShare-ը ցածր մակարդակի կողպեք է, որն ասում է մեզ «մի գցեք այս աղյուսակը, մինչ ես աշխատում եմ»:. Ըստ էության, դա այն ամենն է, ինչ նա անում է:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

ՇԱՐՔԻ ԲԱԺԻՆ - Այս կողպեքը մի փոքր այլ է:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Օրինակ բերենք. SELECT ROW SHARE մեթոդը յուրաքանչյուր տող առանձին կողպելու համար. Այս կերպ ոչ ոք չի կարող ջնջել դրանք կամ փոխել դրանք, մինչ մենք դիտում ենք դրանք:

Postgres Lock Manager-ի բացում: Բրյուս ՄոմջյանԱյսպիսով, ի՞նչ է անում SHARE LOCK-ը: Մենք տեսնում ենք, որ գործարքի ID-ն 681 է SELECT-ի համար: Եվ սա հետաքրքիր է. Ի՞նչ է տեղի ունեցել այստեղ։ Առաջին անգամ մենք տեսնում ենք համարը «Կողպել» դաշտում: Մենք վերցնում ենք գործարքի ID-ն և ասում է, որ այն արգելափակում է բացառիկ ռեժիմով: Այն միայն ասում է, որ ես ունեմ մի շարք, որը տեխնիկապես փակված է աղյուսակում ինչ-որ տեղ: Բայց կոնկրետ որտեղ չի ասում։ Սրան ավելի մանրամասն կանդրադառնանք մի փոքր ուշ:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Այստեղ մենք ասում ենք, որ կողպեքը օգտագործվում է մեր կողմից:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Այսպիսով, բացառիկ կողպեքը բացահայտ ասում է, որ այն բացառիկ է: Եվ նաև, եթե դուք ջնջեք տող այս աղյուսակում, ապա դա այն է, ինչ տեղի կունենա, ինչպես տեսնում եք:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

SHARE EXCLUSIVE-ն ավելի երկար կողպեք է:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Սա (ANALYZE) անալիզատորի հրամանն է, որը կօգտագործվի:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

SHARE LOCK – դուք կարող եք հստակորեն կողպել համօգտագործման ռեժիմում:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Կարող եք նաև ստեղծել եզակի ինդեքս: Իսկ այնտեղ դուք կարող եք տեսնել SHARE LOCK-ը, որը դրանց մի մասն է: Եվ կողպում է սեղանը և վրան դնում SHARE LOCK:

Լռելյայնորեն, SHARE LOCK-ը սեղանի վրա նշանակում է, որ այլ մարդիկ կարող են կարդալ աղյուսակը, բայց ոչ ոք չի կարող այն փոփոխել: Եվ սա հենց այն է, ինչ տեղի է ունենում, երբ ստեղծում եք եզակի ինդեքս:

Եթե ​​ես ստեղծեմ եզակի միաժամանակ ինդեքս, ապա ես կունենամ այլ տեսակի կողպում, քանի որ, ինչպես հիշում եք, միաժամանակ ինդեքսների օգտագործումը նվազեցնում է կողպման պահանջը: Եվ եթե ես օգտագործում եմ նորմալ կողպեք, նորմալ ինդեքս, ապա այդպիսով կկանխեմ աղյուսակի ինդեքսում գրելը, մինչ այն ստեղծվում է: Եթե ​​ես օգտագործում եմ միաժամանակ ինդեքս, ապա ես պետք է օգտագործեմ այլ տեսակի կողպեք:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

ԿԻՍՎԵԼ ԲԱՑԱՌԻԿ ՇԱՐՔ – կրկին այն կարող է սահմանվել բացահայտ (բացահայտորեն):

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Կամ մենք կարող ենք ստեղծել կանոն, այսինքն՝ վերցնել կոնկրետ դեպք, որտեղ այն կօգտագործվի:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

ԲԱՑԱՌԻԿ կողպումը նշանակում է, որ ոչ ոք չի կարող փոխել աղյուսակը:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Այստեղ մենք տեսնում ենք տարբեր տեսակի կողպեքներ:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

ACCESS EXCLUSIVE, օրինակ, արգելափակող հրաման է: Օրինակ, եթե դուք անում եք CLUSTER table, ապա սա կնշանակի, որ այնտեղ ոչ ոք չի կարողանա գրել։ Եվ դա կողպում է ոչ միայն ինքնին աղյուսակը, այլեւ ինդեքսները։

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Սա ACCESS EXCLUSIVE արգելափակման երկրորդ էջն է, որտեղ մենք տեսնում ենք, թե կոնկրետ ինչ է այն արգելափակում աղյուսակում։ Այն կողպում է առանձին սեղանների շարքերը, ինչը բավականին հետաքրքիր է։

Դա այն ամբողջ հիմնական տեղեկությունն է, որը ես ուզում էի տալ: Մենք խոսեցինք կողպեքների, գործարքների ID-ների մասին, խոսեցինք վիրտուալ գործարքների ID-ների, մշտական ​​գործարքների ID-ների մասին:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ հիմա մենք կանցնենք որոշ արգելափակող օրինակների միջով: Սա ամենահետաքրքիր հատվածն է։ Կդիտարկենք շատ հետաքրքիր դեպքեր։ Եվ այս ներկայացման իմ նպատակն է ձեզ ավելի լավ հասկանալ, թե ինչ է իրականում անում Postgres-ը, երբ փորձում է արգելափակել որոշ բաներ: Կարծում եմ, որ նա շատ լավ է կարողանում արգելափակել մասերը:

Եկեք նայենք մի քանի կոնկրետ օրինակների:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Մենք կսկսենք աղյուսակներից և աղյուսակի մեկ տողից: Երբ ես ինչ-որ բան եմ տեղադրում, սեղանի վրա ցուցադրվում են ExclusiveLock, Transaction ID և ExclusiveLock:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Ի՞նչ կլինի, եթե ևս երկու տող տեղադրեմ: Եվ հիմա մեր սեղանն ունի երեք տող: Եվ ես տեղադրեցի մեկ տող և ստացա սա որպես արդյունք: Իսկ եթե մտցնեմ եւս երկու տող, ի՞նչ տարօրինակ կա դրա մեջ։ Այստեղ տարօրինակ բան կա, քանի որ ես երեք տող եմ ավելացրել այս աղյուսակում, բայց ես դեռ երկու տող ունեմ կողպեքի աղյուսակում: Եվ սա ըստ էության Պոստգրեսի հիմնարար պահվածքն է։

Շատերը կարծում են, որ եթե տվյալների բազայում դուք արգելափակում եք 100 տող, ապա ձեզ հարկավոր է ստեղծել 100 կողպեքի գրառում: Եթե ​​ես միանգամից արգելափակեմ 1 տող, ապա ինձ անհրաժեշտ կլինի 000 այդպիսի հարցում։ Իսկ եթե ինձ մի միլիոն կամ միլիարդ է պետք արգելափակելու համար։ Բայց եթե մենք դա անենք, դա այնքան էլ լավ չի աշխատի: Եթե ​​դուք օգտագործել եք համակարգ, որը ստեղծում է արգելափակող գրառումներ յուրաքանչյուր առանձին տողի համար, ապա կարող եք տեսնել, որ դա բարդ է: Քանի որ դուք պետք է անմիջապես սահմանեք կողպեքի աղյուսակը, որը կարող է լցվել, բայց Postgres-ը դա չի անում:

Եվ այն, ինչ իսկապես կարևոր է այս սլայդի համար, այն է, որ այն հստակ ցույց է տալիս, որ կա մեկ այլ համակարգ, որն աշխատում է MVCC-ի ներսում, որը կողպում է առանձին տողերը: Այսպիսով, երբ դուք արգելափակում եք միլիարդավոր տողեր, Postgres-ը չի ստեղծում մեկ միլիարդ առանձին կողպման հրամաններ: Եվ սա շատ լավ է ազդում արտադրողականության վրա։

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Ինչ վերաբերում է թարմացմանը: Ես այժմ թարմացնում եմ տողը, և դուք կարող եք տեսնել, որ այն կատարել է միանգամից երկու տարբեր գործողություն: Այն միաժամանակ կողպեց սեղանը, բայց նաև կողպեց ինդեքսը։ Եվ նրան անհրաժեշտ էր կողպել ինդեքսը, քանի որ այս աղյուսակում կան եզակի սահմանափակումներ: Եվ մենք ուզում ենք համոզվել, որ ոչ ոք չի փոխի այն, ուստի մենք արգելափակում ենք այն:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Ի՞նչ կլինի, եթե ես ուզում եմ թարմացնել երկու տող: Եվ մենք տեսնում ենք, որ նա իրեն նույն կերպ է պահում։ Մենք կրկնակի շատ թարմացումներ ենք անում, բայց ճիշտ նույն թվով կողպեքի գծեր:

Եթե ​​ձեզ հետաքրքրում է, թե ինչպես է դա անում Postgres-ը, դուք պետք է լսեք իմ ելույթները MVCC-ի վերաբերյալ՝ իմանալու համար, թե ինչպես է Postgres-ը ներքուստ նշում այս տողերը, որոնք այն փոխում է: Իսկ Postgres-ը դա անում է ոչ թե սեղանի փակման մակարդակով, այլ ավելի ցածր և արդյունավետ մակարդակով:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Իսկ եթե ես ուզում եմ ինչ-որ բան ջնջել: Եթե ​​ես ջնջեմ, օրինակ, մեկ տող, և ես դեռ ունեմ իմ երկու արգելափակող մուտքերը, և նույնիսկ եթե ես ուզում եմ ջնջել դրանք բոլորը, դրանք դեռ կան:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Իսկ ես, օրինակ, ուզում եմ 1 տող մտցնել, հետո կամ ջնջել, կամ ավելացնել 000 տող, հետո այդ առանձին տողերը, որ ավելացնում եմ կամ փոխում եմ, այստեղ չեն գրանցվում։ Դրանք գրված են ավելի ցածր մակարդակով հենց շարքի ներսում: Եվ MVCC ելույթի ժամանակ ես մանրամասն խոսեցի այս մասին։ Բայց շատ կարևոր է, երբ դուք վերլուծում եք կողպեքները, համոզվեք, որ դուք կողպվում եք սեղանի մակարդակով և չեք տեսնում, թե ինչպես են առանձին տողերը գրանցվում այստեղ:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Ինչ վերաբերում է բացահայտ արգելափակմանը:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եթե ​​ես սեղմում եմ թարմացում, ապա երկու տող կողպված է: Եվ եթե ես ընտրեմ բոլորին և սեղմեմ «թարմացնել ամենուր», ապա ես դեռ ունեմ երկու արգելափակող գրառում:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Մենք առանձին գրառումներ չենք ստեղծում յուրաքանչյուր առանձին տողի համար: Քանի որ հետո արտադրողականությունը նվազում է, այն կարող է չափազանց շատ լինել: Եվ մենք կարող ենք հայտնվել տհաճ իրավիճակում։

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ նույն բանը, եթե մենք կիսում ենք, մենք կարող ենք դա անել 30 անգամ:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Մենք վերականգնում ենք մեր աղյուսակը, ջնջում ենք ամեն ինչ, հետո նորից դնում ենք մեկ տող:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Մեկ այլ վարքագիծ, որը դուք տեսնում եք Postgres-ում, որը շատ լավ հայտնի և ցանկալի է, այն է, որ դուք կարող եք կատարել թարմացում կամ ընտրություն: Եվ դուք կարող եք դա անել միաժամանակ: Իսկ ընտրելը չի ​​արգելափակում թարմացումը և նույնը հակառակ ուղղությամբ։ Ընթերցողին ասում ենք՝ գրողին մի արգելափակի, գրողն էլ ընթերցողին չի արգելափակել։

Ես ձեզ ցույց կտամ դրա օրինակը: Ես հիմա ընտրություն կանեմ. Այնուհետև մենք կանենք INSERT-ը: Եվ հետո դուք կարող եք տեսնել - 694: Դուք կարող եք տեսնել գործարքի ID-ն, որն իրականացրել է այս ներդրումը: Եվ դա այդպես է աշխատում:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ եթե ես հիմա նայեմ իմ backend ID-ին, այն այժմ 695 է:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ ես տեսնում եմ, որ 695-ը հայտնվում է իմ աղյուսակում:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ եթե ես թարմացնեմ այստեղ այսպես, ապա ես ստանում եմ այլ դեպք: Այս դեպքում 695-ը բացառիկ կողպեք է, և թարմացումը նույն վարքագիծն ունի, բայց դրանց միջև կոնֆլիկտ չկա, ինչը բավականին անսովոր է։

Եվ դուք կարող եք տեսնել, որ վերևում այն ​​ShareLock է, իսկ ներքևում՝ ExclusiveLock: Եվ երկու գործարքներն էլ ստացվեցին։

Եվ դուք պետք է լսեք իմ ելույթը MVCC-ում, որպեսզի հասկանաք, թե ինչպես է դա տեղի ունենում: Բայց սա օրինակ է, որ դուք կարող եք դա անել միաժամանակ, այսինքն՝ կատարել SELECT և UPDATE միաժամանակ:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եկեք զրոյականացնենք և կատարենք ևս մեկ գործողություն:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եթե ​​փորձեք միաժամանակ երկու թարմացում գործարկել նույն շարքում, այն կարգելափակվի: Եվ հիշեք, ես ասացի, որ ընթերցողը չի արգելափակում գրողին, գրողն էլ չի արգելափակում ընթերցողին, բայց մի գրողը արգելափակում է մյուս գրողին։ Այսինքն՝ մենք չենք կարող ունենալ երկու հոգի միաժամանակ թարմացնել նույն տողը։ Դուք պետք է սպասեք, մինչև դրանցից մեկը ավարտի:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ սա ցույց տալու համար ես կնայեմ Lockdemo աղյուսակին: Եվ մենք կանդրադառնանք մեկ շարքին: Մեկ գործարքի համար 698.

Մենք սա թարմացրել ենք 2-ի: 699-ը առաջին թարմացումն է: Եվ այն հաջողված էր, կամ այն ​​առկախ գործարքի մեջ է և սպասում է, որ մենք հաստատենք կամ չեղարկենք:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Բայց նայեք մեկ այլ բան. 2/51-ը մեր առաջին գործարքն է, մեր առաջին նիստը: 3/112-ը վերևից եկած երկրորդ հարցումն է, որը փոխեց այդ արժեքը 3-ի: Եվ եթե նկատում եք, վերևն ինքն իրեն կողպել է, որը 699 է: Բայց 3/112-ը չի տվել կողպեքը: Lock_mode սյունակը ասում է, թե ինչ է սպասում: Այն ակնկալում է 699: Եվ եթե նայեք, թե որտեղ է 699-ը, այն ավելի բարձր է: Իսկ ի՞նչ արեց առաջին նիստը։ Նա ստեղծել է բացառիկ կողպեք իր սեփական գործարքի ID-ում: Պոստգրեսն այսպես է անում։ Այն արգելափակում է իր սեփական գործարքի ID-ն: Եվ եթե ցանկանում եք սպասել, որ ինչ-որ մեկը հաստատի կամ չեղարկի, ապա դուք պետք է սպասեք, քանի դեռ կա սպասվող գործարք: Եվ դրա համար մենք կարող ենք տեսնել տարօրինակ գիծ.

Եկեք նորից նայենք. Ձախ կողմում մենք տեսնում ենք մեր մշակման ID-ն: Երկրորդ սյունակում մենք տեսնում ենք մեր վիրտուալ գործարքի ID-ն, իսկ երրորդում՝ lock_type: Ինչ է սա նշանակում? Ըստ էության, այն, ինչ ասում է, այն է, որ այն արգելափակում է գործարքի ID-ն: Բայց ուշադրություն դարձրեք, որ ներքևի բոլոր տողերում ասվում է հարաբերություն: Եվ այսպես, դուք ունեք երկու տեսակի կողպեքներ սեղանի վրա: Առկա է կապի կողպեք։ Եվ հետո կա գործարքների արգելափակում, որտեղ դուք ինքնուրույն արգելափակում եք, ինչը հենց այն է, ինչ տեղի է ունենում առաջին շարքում կամ հենց ներքևում, որտեղ գտնվում է գործարքը, որտեղ մենք սպասում ենք, որ 699-ը ավարտի իր աշխատանքը:

Ես կտեսնեմ, թե ինչ կլինի այստեղ: Եվ այստեղ երկու բան տեղի է ունենում միաժամանակ. Դուք առաջին շարքում նայում եք գործարքի ID-ի կողպեքին, որն ինքն իրեն կողպում է: Եվ նա արգելափակում է իրեն, որպեսզի մարդիկ սպասեն:

Եթե ​​նայեք 6-րդ տողին, ապա դա նույն մուտքն է, ինչ առաջինը։ Եվ հետևաբար 699 գործարքն արգելափակված է։ 700-ը նույնպես ինքնափակվում է։ Եվ հետո ներքևի տողում կտեսնեք, որ մենք սպասում ենք 699-ին, որպեսզի ավարտի իր աշխատանքը:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Իսկ lock_type, tuple-ում տեսնում եք թվեր:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Դուք կարող եք տեսնել, որ դա 0/10 է: Եվ սա էջի համարն է, ինչպես նաև այս կոնկրետ տողի օֆսեթը:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ դուք տեսնում եք, որ այն դառնում է 0/11, երբ մենք թարմացնում ենք:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Բայց իրականում դա 0/10 է, քանի որ այս գործողությանը սպասվում է։ Մենք հնարավորություն ունենք տեսնելու, որ սա այն շարքն է, որը ես սպասում եմ հաստատել:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Երբ մենք դա հաստատեցինք և սեղմեցինք commit, և երբ թարմացումն ավարտվի, սա այն է, ինչ մենք կրկին ստանում ենք: Գործարք 700-ը միակ կողպեքն է, այն չի սպասում ուրիշի, քանի որ այն կատարվել է: Այն պարզապես սպասում է գործարքի ավարտին: Երբ 699-ը վերջանում է, մենք այլևս ոչ մի բանի չենք սպասում: Եվ հիմա գործարք 700 ասում է, որ ամեն ինչ լավ է, որ այն ունի բոլոր կողպեքները, որոնք անհրաժեշտ են բոլոր թույլատրված սեղանների վրա:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ այս ամբողջն էլ ավելի բարդացնելու համար մենք ստեղծում ենք մեկ այլ տեսակետ, որն այս անգամ մեզ կտրամադրի հիերարխիա։ Ես չեմ ակնկալում, որ դուք կհասկանաք այս խնդրանքը: Բայց սա մեզ ավելի հստակ պատկերացում կտա, թե ինչ է կատարվում:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Սա ռեկուրսիվ տեսք է, որն ունի նաև մեկ այլ բաժին: Եվ հետո ամեն ինչ նորից ի մի է բերում: Եկեք օգտագործենք սա:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Ի՞նչ կլինի, եթե մենք կատարենք երեք միաժամանակյա թարմացում և ասենք, որ շարքն այժմ երեքն է: Եվ մենք կփոխենք 3-ը 4-ի:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ ահա մենք տեսնում ենք 4. Եվ գործարքի ID 702:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ հետո ես կփոխեմ 4-ը 5-ի և 5-ը 6-ի, և 6-ը 7-ի: Եվ ես կշարունակեմ մի շարք մարդկանց, ովքեր կսպասեն այս մեկ գործարքի ավարտին:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ ամեն ինչ պարզ է դառնում. Ո՞րն է առաջին շարքը: Սա 702 է: Սա գործարքի ID-ն է, որն ի սկզբանե սահմանել է այս արժեքը: Ի՞նչ է գրված իմ շնորհված սյունակում: Ես ունեմ նշաններ f. Սրանք իմ թարմացումներն են, որոնք (5, 6, 7) չեն կարող հաստատվել, քանի որ մենք սպասում ենք գործարքի ID 702-ի ավարտին: Այնտեղ մենք ունենք գործարքի ID արգելափակում: Եվ սա հանգեցնում է 5 գործարքային ID կողպման:

Իսկ եթե նայեք 704-ին, ապա 705-ին, այնտեղ դեռ ոչինչ գրված չէ, քանի որ նրանք դեռ չգիտեն, թե ինչ է կատարվում: Ուղղակի գրում են, որ պատկերացում չունեն, թե ինչ է կատարվում։ Եվ նրանք պարզապես կգնան քնելու, քանի որ սպասում են, որ ինչ-որ մեկը ավարտի և արթնանա, երբ հնարավորություն լինի շարք փոխելու։

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Ահա թե ինչ տեսք ունի. Պարզ է, որ նրանք բոլորը սպասում են 12-րդ տողին։

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Սա այն է, ինչ մենք տեսանք այստեղ: Ահա 0/12:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Այսպիսով, երբ առաջին գործարքը հաստատվի, դուք կարող եք տեսնել այստեղ, թե ինչպես է աշխատում հիերարխիան: Եվ հիմա ամեն ինչ պարզ է դառնում. Նրանք բոլորը դառնում են մաքուր: Եվ նրանք իրականում դեռ սպասում են։

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Ահա թե ինչ է կատարվում. 702 պարտավորվում է. Եվ հիմա 703-ը ստանում է այս տողի կողպումը, և այնուհետև 704-ը սկսում է սպասել 703-ի կատարմանը: Եվ 705-ը նույնպես սպասում է սրան: Եվ երբ այս ամենը ավարտվում է, նրանք ինքնամաքրվում են։ Եվ ուզում եմ նշել, որ բոլորը շարվում են։ Եվ սա շատ նման է խցանման իրավիճակին, երբ բոլորը սպասում են առաջին մեքենային։ Առաջին մեքենան կանգնում է, և բոլորը երկար հերթ են կանգնում։ Հետո այն շարժվում է, հետո հաջորդ մեքենան կարող է առաջ քշել և ստանալ իր բլոկը և այլն։

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ եթե սա ձեզ բավական բարդ չթվաց, ապա այժմ մենք ձեզ հետ կխոսենք փակուղիների մասին: Ես չգիտեմ, թե ձեզնից ով է հանդիպել նրանց: Սա բավականին տարածված խնդիր է տվյալների բազայի համակարգերում: Բայց փակուղիներն այն են, երբ մի նիստը սպասում է մեկ այլ նիստի՝ ինչ-որ բան անելու համար: Եվ այս պահին հերթական նիստն է սպասում առաջին նիստին՝ ինչ-որ բան անելու համար։

Եվ, օրինակ, եթե Իվանն ասի. Եվ նա ասում է. «Ոչ, ես այն քեզ չեմ տա, եթե դու ինձ չտաս»: Եվ մենք հայտնվում ենք փակուղային իրավիճակում։ Համոզված եմ, որ Իվանը դա չի անի, բայց դու հասկանում ես այն իմաստը, որ մենք ունենք երկու հոգի, ովքեր ցանկանում են ինչ-որ բան ստանալ, և նրանք պատրաստ չեն տալ այն, քանի դեռ դիմացինը չի տալիս իրենց ուզածը։ Եվ լուծում չկա։

Եվ ըստ էության, ձեր տվյալների բազան պետք է դա հայտնաբերի: Եվ հետո դուք պետք է ջնջեք կամ փակեք նիստերից մեկը, քանի որ հակառակ դեպքում դրանք ընդմիշտ կմնան այնտեղ: Եվ մենք դա տեսնում ենք տվյալների բազաներում, տեսնում ենք օպերացիոն համակարգերում: Եվ բոլոր տեղերում, որտեղ մենք ունենք զուգահեռ գործընթացներ, դա կարող է լինել։

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ հիմա մենք կտեղադրենք երկու փակուղի. Կդնենք 50-ը և 80-ը: Առաջին շարքում ես կթարմացնեմ 50-ից 50-ը: Ես կստանամ գործարքի համարը 710:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ հետո ես կփոխեմ 80-ը 81-ի, իսկ 50-ը՝ 51-ի:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ ահա թե ինչ տեսք կունենա այն. Եվ այսպես, 710-ում մի շարք արգելափակված է, և 711-ը սպասում է հաստատման: Մենք սա տեսանք, երբ թարմացրինք: 710-ը մեր շարքի սեփականատերն է։ Իսկ 711-ը սպասում է 710-ին՝ գործարքն ավարտելու համար:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ նույնիսկ ասում է, թե որ շարքում են փակուղիները: Եվ ահա, որտեղ այն սկսում է տարօրինակ դառնալ:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Այժմ մենք թարմացնում ենք 80-ից 80-ը:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ այստեղից են սկսվում փակուղիները։ 710-ը սպասում է 711-ի պատասխանին, իսկ 711-ը սպասում է 710-ին: Եվ սա լավ ավարտ չի ունենա: Եվ սրանից ելք չկա։ Եվ նրանք միմյանցից արձագանք են ակնկալելու։

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ դա պարզապես կսկսի ամեն ինչ հետաձգել։ Իսկ մենք դա չենք ուզում։

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ Postgres-ը միջոցներ ունի նկատելու, երբ դա տեղի է ունենում: Եվ երբ դա տեղի է ունենում, դուք ստանում եք այս սխալը: Եվ սրանից պարզ է դառնում, որ այսինչ գործընթացն այլ գործընթացից սպասում է SHARE LOCK-ին, այսինքն՝ արգելափակված է 711 պրոցեսով։ Եվ այդ պրոցեսը սպասում էր, որ SHARE LOCK տրվեր այսինչ գործարքի ID-ի վրա և արգելափակվեց այսինչ գործընթացով։ Ուստի այստեղ փակուղային իրավիճակ է։

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Կա՞ն եռակողմ փակուղիներ։ Դա հնարավոր է? Այո՛։

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Այս թվերը մենք մուտքագրում ենք աղյուսակ: 40-ը փոխում ենք 40-ի, արգելափակում ենք անում։

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

60-ը փոխում ենք 61-ի, 80-ը՝ 81-ի։

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ հետո մենք փոխում ենք 80, իսկ հետո բում!

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Իսկ 714-ը հիմա սպասում է 715-ին: 716-րդը սպասում է 715-ին: Եվ դրա դեմ ոչինչ անել հնարավոր չէ:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Այստեղ արդեն երկու հոգի չկա, այստեղ արդեն երեք հոգի կա։ Ես քեզնից ինչ-որ բան եմ ուզում, սա երրորդ անձից ինչ-որ բան է ուզում, իսկ երրորդն ինձանից: Եվ մենք հայտնվում ենք եռակողմ սպասման մեջ, քանի որ մենք բոլորս սպասում ենք, որ դիմացինը ավարտի այն, ինչ պետք է անի:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ Postgres-ը գիտի, թե որ շարքում է դա տեղի ունենում: Եվ այսպես, այն ձեզ կտա հետևյալ հաղորդագրությունը, որը ցույց է տալիս, որ դուք խնդիր ունեք, երբ երեք մուտքերն արգելափակում են միմյանց: Եվ այստեղ սահմանափակումներ չկան։ Սա կարող է լինել այն դեպքը, երբ 20 գրառումներ արգելափակում են միմյանց:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Հաջորդ խնդիրը սերիականացման ենթակա է.

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եթե ​​հատուկ սերիական կողպեք:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ մենք վերադառնում ենք 719: Դրա ելքը միանգամայն նորմալ է:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ դուք կարող եք սեղմել՝ գործարքը սերիականացնելու համար:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ դուք հասկանում եք, որ այժմ ունեք այլ տեսակի SA կողպեք, դա նշանակում է սերիականացման:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ այսպես, մենք ունենք նոր տեսակի կողպեք, որը կոչվում է SARieadLock, որը սերիական կողպեք է և թույլ է տալիս մուտքագրել սերիալներ:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ նաև կարող եք տեղադրել եզակի ինդեքսներ:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Այս աղյուսակում մենք ունենք եզակի ինդեքսներ։

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Այսպիսով, եթե ես այստեղ դնեմ համարը 2, ուրեմն կունենամ 2: Բայց ամենավերևում, ես դրեցի ևս 2-ը: Եվ դուք կարող եք տեսնել, որ 721-ն ունի բացառիկ կողպեք: Բայց հիմա 722-ը սպասում է 721-ին, որպեսզի ավարտի իր գործողությունը, քանի որ չի կարող 2-ը տեղադրել, քանի դեռ չիմանալ, թե ինչ է լինելու 721-ի հետ:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Իսկ եթե մենք ենթ գործարք կատարենք.

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Այստեղ մենք ունենք 723:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Իսկ եթե պահենք կետը և հետո թարմացնենք այն, ապա կստանանք գործարքի նոր ID: Սա վարքագծի ևս մեկ օրինակ է, որը դուք պետք է տեղյակ լինեք: Եթե ​​մենք վերադարձնենք սա, ապա գործարքի ID-ն անհետանում է: 724-ը հեռանում է. Բայց հիմա մենք ունենք 725:

Այսպիսով, ի՞նչ եմ ես փորձում անել այստեղ: Ես փորձում եմ ձեզ ցույց տալ անսովոր կողպեքների օրինակներ, որոնք դուք կարող եք գտնել. լինի դա սերիականացվող կողպեքներ, թե SAVEPOINT, սրանք տարբեր տեսակի կողպեքներ են, որոնք կհայտնվեն կողպեքի աղյուսակում:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Սա բացահայտ (բացահայտ) կողպեքների ստեղծումն է, որոնք ունեն pg_advisory_lock:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ դուք տեսնում եք, որ արգելափակման տեսակը նշված է որպես խորհրդատվական: Եվ այստեղ կարմիրով գրված է «խորհրդատվական»: Եվ դուք կարող եք միաժամանակ արգելափակել այսպես pg_advisory_unlock-ով:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ վերջում ես կցանկանայի ձեզ ցույց տալ ևս մեկ խելամիտ բան. Ես կստեղծեմ մեկ այլ տեսարան. Բայց ես միանալու եմ pg_locks աղյուսակին pg_stat_activity աղյուսակով։ Եվ ինչու եմ ես ուզում դա անել: Որովհետև դա ինձ թույլ կտա նայել և տեսնել բոլոր ընթացիկ նիստերը և տեսնել, թե կոնկրետ ինչ կողպեքների են նրանք սպասում: Եվ սա բավականին հետաքրքիր է, երբ մենք հավաքում ենք կողպեքի աղյուսակը և հարցման աղյուսակը:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ այստեղ մենք ստեղծում ենք pg_stat_view:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Եվ մենք թարմացնում ենք շարքը մեկ առ մեկ: Եվ ահա մենք տեսնում ենք 724-ը: Եվ հետո մենք թարմացնում ենք մեր շարքը երեքի: Իսկ ի՞նչ եք տեսնում այստեղ հիմա: Սրանք հարցումներ են, այսինքն՝ դուք տեսնում եք հարցումների ամբողջ ցանկը, որոնք նշված են ձախ սյունակում: Եվ հետո աջ կողմում դուք կարող եք տեսնել խցանումները և այն, ինչ նրանք ստեղծում են: Եվ դա կարող է ավելի պարզ լինել ձեզ համար, որպեսզի դուք ստիպված չլինեք ամեն անգամ վերադառնալ յուրաքանչյուր նիստին և տեսնել, արդյոք դուք պետք է միանաք դրան, թե ոչ: Նրանք դա անում են մեզ համար:

Մեկ այլ հատկանիշ, որը շատ օգտակար է pg_blocking_pids. Դուք հավանաբար երբեք չեք լսել նրա մասին: Ինչ է նա անում? Այն թույլ է տալիս մեզ ասել, որ այս նստաշրջանի համար 11740-ն ինչ կոնկրետ գործընթացի ID-ներ է սպասում: Եվ դուք կարող եք տեսնել, որ 11740-ը սպասում է 724-ին: Իսկ 724-ը ամենավերևում է: Իսկ 11306-ը ձեր գործընթացի ID-ն է: Ըստ էության, այս գործառույթը անցնում է ձեր կողպեքի սեղանով: Եվ ես գիտեմ, որ դա մի փոքր բարդ է, բայց դուք կարողանում եք դա հասկանալ: Ըստ էության, այս ֆունկցիան անցնում է այս կողպեքի աղյուսակով և փորձում է գտնել, թե որտեղ է այս գործընթացի ID-ին տրված կողպեքները, որոնց վրա նա սպասում է: Եվ այն նաև փորձում է պարզել, թե որ գործընթացի ID ունի կողպեքին սպասվող գործընթացը: Այսպիսով, դուք կարող եք գործարկել այս գործառույթը pg_blocking_pids.

Եվ սա կարող է շատ օգտակար լինել: Մենք սա ավելացրել ենք միայն 9.6 տարբերակում, ուստի այս ֆունկցիան ընդամենը 5 տարեկան է, բայց այն շատ, շատ օգտակար է: Եվ նույնը վերաբերում է երկրորդ խնդրանքին. Այն ցույց է տալիս հենց այն, ինչ մենք պետք է տեսնենք:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Սա այն է, ինչի մասին ես ուզում էի խոսել ձեզ հետ: Եվ ինչպես սպասում էի, մենք սպառեցինք մեր ամբողջ ժամանակը, քանի որ սլայդները շատ էին: Իսկ սլայդները հասանելի են ներբեռնման համար: Ցանկանում եմ շնորհակալություն հայտնել այստեղ լինելու համար: Համոզված եմ, որ դուք կվայելեք համաժողովի մնացած մասը, շատ շնորհակալ եմ:

Հարցեր.

Օրինակ, եթե ես փորձում եմ թարմացնել տողերը, իսկ երկրորդ նիստը փորձում է ջնջել ամբողջ աղյուսակը: Ինչքան հասկացա, մտադրության կողպեքի նման մի բան պետք է լինի։ Պոստգրեսում կա՞ նման բան։

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Վերադառնանք հենց սկզբին։ Դուք կարող եք հիշել, որ երբ ինչ-որ բան եք անում, օրինակ, երբ կատարում եք SELECT, մենք թողարկում ենք AccessShareLock: Եվ դա խանգարում է սեղանը գցել: Այսպիսով, եթե դուք, օրինակ, ցանկանում եք թարմացնել աղյուսակի տողը կամ ջնջել տողը, ապա ինչ-որ մեկը չի կարող միաժամանակ ջնջել ամբողջ աղյուսակը, քանի որ դուք այս AccessShareLock-ը պահում եք ամբողջ աղյուսակի և տողի վրա: Եվ երբ ավարտեք, նրանք կարող են ջնջել այն: Բայց մինչ դուք ուղղակիորեն ինչ-որ բան փոխեք այնտեղ, նրանք չեն կարողանա դա անել:

Եկեք դա նորից անենք: Անցնենք ջնջման օրինակին։ Եվ դուք տեսնում եք, թե ինչպես է ամբողջ սեղանի վերևում գտնվող շարքում բացառիկ կողպեք:

Սա կողպեքի բացառիկ տեսք կունենա, չէ՞:

Այո, կարծես թե: Ես հասկանում եմ, թե ինչի մասին եք խոսում։ Դուք ասում եք, որ եթե ես SELECT անեմ, ապա ես ունեմ ShareExclusive և այն դարձնեմ Row Exclusive, դա խնդիր է դառնում: Բայց զարմանալիորեն սա խնդիր չի առաջացնում: Սա կարծես կողպման աստիճանի բարձրացում է, բայց, ըստ էության, ես ունեմ կողպեք, որը կանխում է ջնջումը: Եվ հիմա, երբ այս կողպեքն ավելի հզոր եմ դարձնում, այն դեռ կանխում է ջնջումը։ Այնպես որ, այնպես չէ, որ ես բարձրանում եմ: Այսինքն, դա թույլ չտվեց, որ դա տեղի ունենա, երբ այն նույնպես ավելի ցածր մակարդակի վրա էր, այնպես որ, երբ ես բարձրացնում եմ դրա մակարդակը, այն դեռ թույլ չի տալիս աղյուսակը ջնջել:

Ես հասկանում եմ, թե ինչի մասին եք խոսում։ Այստեղ կողպեքի էսկալացիայի դեպք չկա, երբ դուք փորձում եք հրաժարվել մեկ կողպեքից՝ ավելի ամուր ներդնելու համար: Այստեղ դա պարզապես մեծացնում է այս կանխարգելումը ամբողջ տախտակի վրա, այնպես որ դա որևէ կոնֆլիկտ չի առաջացնում: Բայց դա լավ հարց է: Շատ շնորհակալ եմ այս հարցնելու համար:

Ի՞նչ պետք է անենք, որպեսզի խուսափենք փակուղային իրավիճակից, երբ ունենք բազմաթիվ նիստեր, մեծ թվով օգտատերեր։

Postgres-ը ավտոմատ կերպով նկատում է փակուղային իրավիճակները: Եվ դա ավտոմատ կերպով կջնջի նիստերից մեկը: Մահացած արգելափակումից խուսափելու միակ միջոցը մարդկանց նույն հերթականությամբ արգելափակելն է: Այսպիսով, երբ նայում եք ձեր դիմումին, հաճախ փակուղիների պատճառ է դառնում... Եկեք պատկերացնենք, որ ես ուզում եմ արգելափակել երկու տարբեր բաներ: Մի հավելված կողպում է աղյուսակ 1-ը, իսկ մյուս հավելվածը կողպում է 2-ը, այնուհետև աղյուսակ 1-ը: Եվ փակուղուց խուսափելու ամենահեշտ ձևը ձեր հավելվածին նայելն է և փորձել համոզվել, որ կողպումը տեղի է ունենում նույն հերթականությամբ բոլոր հավելվածներում: Իսկ դա սովորաբար վերացնում է խնդիրների 80%-ը, քանի որ բոլոր տեսակի մարդիկ գրում են այս հավելվածները։ Իսկ եթե դրանք արգելափակեք նույն հերթականությամբ, ապա փակուղային իրավիճակի չեք հանդիպի։

Շատ շնորհակալ եմ ձեր կատարման համար: Դուք խոսեցիք վակուումի լրիվ մասին և, եթե ճիշտ եմ հասկանում, վակուումային լրիվ խեղաթյուրում է առանձին պահեստում գտնվող գրառումների կարգը, ուստի ընթացիկ գրառումներն անփոփոխ են պահում։ Ինչու՞ է վակուումը լրիվ բացառապես կողպման հասանելիություն և ինչու է այն հակասում գրելու գործողություններին:

Դա լավ հարց է: Պատճառն այն է, որ լի վակուումը վերցնում է սեղանը։ Եվ մենք ըստ էության ստեղծում ենք աղյուսակի նոր տարբերակը: Իսկ սեղանը նոր կլինի։ Պարզվում է՝ սա կլինի աղյուսակի բոլորովին նոր տարբերակը։ Եվ խնդիրն այն է, որ երբ մենք դա անում ենք, մենք չենք ուզում, որ մարդիկ կարդան այն, քանի որ մեզ անհրաժեշտ է, որ նրանք տեսնեն նոր աղյուսակը: Եվ այսպես, սա կապված է նախորդ հարցի հետ: Եթե ​​մենք կարողանայինք միաժամանակ կարդալ, մենք չէինք կարողանա այն տեղափոխել և մարդկանց ուղղորդել դեպի նոր սեղան: Մենք պետք է սպասենք, որ բոլորը ավարտեն այս աղյուսակի ընթերցումը, և, հետևաբար, դա, ըստ էության, կողպեքի բացառիկ իրավիճակ է:
Մենք պարզապես ասում ենք, որ մենք կողպում ենք սկզբից, քանի որ գիտենք, որ հենց վերջում մեզ անհրաժեշտ կլինի բացառիկ կողպեք, որպեսզի բոլորին տեղափոխենք նոր օրինակ: Այսպիսով, մենք կարող ենք պոտենցիալ լուծել դա: Եվ մենք դա անում ենք այս կերպ՝ միաժամանակյա ինդեքսավորմամբ։ Բայց դա անելը շատ ավելի դժվար է։ Եվ սա շատ առնչվում է կողպեքի բացառիկ մասին ձեր նախորդ հարցին:

Հնարավո՞ր է արդյոք Postgres-ին կողպման ժամանակացույց ավելացնել: Oracle-ում կարող եմ, օրինակ, գրել «select to update» ու թարմացնելուց առաջ սպասել 50 վայրկյան։ Լավ էր դիմումի համար։ Բայց Պոստգրեսում ես կամ պետք է դա անեմ անմիջապես և ընդհանրապես չսպասեմ, կամ սպասեմ որոշ ժամանակ:

Այո, դուք կարող եք ընտրել ձեր կողպեքների, ձեր կողպեքների վրա ժամանակացույց: Կարող եք նաև թողարկել «no way» հրամանը, որը... եթե չկարողանաք անմիջապես ձեռք բերել կողպեքը: Հետևաբար, կա՛մ կողպեքի դադար, կա՛մ այլ բան, որը թույլ կտա դա անել: Սա չի արվում շարահյուսական մակարդակում: Սա արվում է որպես փոփոխական սերվերի վրա: Երբեմն սա չի կարող օգտագործվել:

Կարո՞ղ եք բացել 75-րդ սլայդը:

Այո:

Postgres Lock Manager-ի բացում: Բրյուս Մոմջյան

Իսկ իմ հարցը հետեւյալն է. Ինչո՞ւ են թարմացման երկու գործընթացներն էլ ակնկալում 703:

Եվ սա մեծ հարց է: Ես, ի դեպ, չեմ հասկանում, թե ինչու է Պոստգրեսը դա անում։ Բայց երբ 703-ը ստեղծվեց, այն սպասում էր 702-ին: Եվ երբ 704-ը և 705-ը հայտնվում են, թվում է, թե նրանք չգիտեն, թե ինչ են սպասում, քանի որ այնտեղ դեռ ոչինչ չկա: Իսկ Postgres-ը դա անում է այսպես. երբ դուք չեք կարողանում կողպեք ստանալ, գրում է «Ի՞նչ իմաստ ունի ձեզ մշակել», քանի որ դուք արդեն սպասում եք ինչ-որ մեկին: Այսպիսով, մենք պարզապես թույլ կտանք, որ այն կախված լինի օդում, այն ընդհանրապես չի թարմացնի: Բայց ի՞նչ եղավ այստեղ։ Հենց որ 702-ն ավարտեց գործընթացը և 703-ը ստացավ իր կողպեքը, համակարգը վերադարձավ: Եվ նա ասաց, որ հիմա երկու հոգի ունենք, ովքեր սպասում են։ Եվ հետո եկեք թարմացնենք դրանք միասին: Եվ նշենք, որ երկուսն էլ սպասում են։

Ես չգիտեմ, թե ինչու է Պոստգրեսը դա անում: Բայց կա մի խնդիր, որը կոչվում է f…. Ինձ թվում է՝ սա ռուսերեն տերմին չէ։ Սա այն դեպքում, երբ բոլորը սպասում են մեկ դղյակի, նույնիսկ եթե կա 20 իշխանություն, որ սպասում է ամրոցին։ Եվ հանկարծ նրանք բոլորն արթնանում են միաժամանակ։ Եվ բոլորը սկսում են փորձել արձագանքել։ Բայց համակարգը այնպես է անում, որ բոլորը սպասում են 703-ին: Որովհետև նրանք բոլորը սպասում են, և մենք անմիջապես կշարենք բոլորին: Եվ եթե հայտնվի որևէ այլ նոր հարցում, որը ստեղծվել է սրանից հետո, օրինակ՝ 707, ապա նորից դատարկություն կլինի։

Եվ ինձ թվում է, որ դա արվում է, որպեսզի ասենք, որ այս փուլում 702-ը սպասում է 703-ին, և բոլոր նրանք, ովքեր դրանից հետո գան, որևէ մուտք այս ոլորտում չեն ունենա։ Բայց հենց որ առաջին մատուցողը հեռանում է, բոլոր նրանք, ովքեր այդ պահին սպասում էին թարմացումից առաջ, նույն նշանն են ստանում։ Եվ այսպես, կարծում եմ, սա արվում է, որպեսզի մենք կարողանանք ընթացք տալ, որպեսզի դրանք պատշաճ կերպով պատվիրվեն:

Ես սրան միշտ դիտել եմ որպես բավականին տարօրինակ երեւույթի։ Քանի որ այստեղ, օրինակ, մենք ընդհանրապես չենք թվարկում դրանք: Բայց ինձ թվում է, որ ամեն անգամ, երբ նոր կողպեք ենք տալիս, նայում ենք բոլոր նրանց, ովքեր սպասումի մեջ են։ Հետո բոլորին շարում ենք։ Եվ հետո ցանկացած նոր, որը գալիս է, հերթ է մտնում միայն այն ժամանակ, երբ հաջորդ անձը ավարտում է մշակումը: Շատ լավ հարց. Շատ շնորհակալ եմ ձեր հարցի համար:

Ինձ թվում է, որ շատ ավելի տրամաբանական է, երբ 705-ն ակնկալում է 704:

Բայց այստեղ խնդիրը հետեւյալն է. Տեխնիկապես դուք կարող եք արթնանալ մեկին կամ մյուսին: Եվ այսպես, մենք կարթնանանք մեկին կամ մյուսին: Բայց ի՞նչ է կատարվում համակարգում։ Դուք կարող եք տեսնել, թե ինչպես է վերևում գտնվող 703-ն արգելափակել իր սեփական գործարքի ID-ն: Այսպես է աշխատում Postgres-ը։ Իսկ 703-ն արգելափակված է իր սեփական գործարքի ID-ով, այնպես որ, եթե ինչ-որ մեկը ցանկանում է սպասել, ապա նա կսպասի 703-ին: Եվ, ըստ էության, 703-ն ավարտում է: Եվ միայն դրա ավարտից հետո է գործընթացներից մեկն արթնանում։ Եվ մենք չգիտենք, թե կոնկրետ ինչ կլինի այս գործընթացը: Հետո ամեն ինչ աստիճանաբար մշակում ենք։ Բայց պարզ չէ, թե որ գործընթացն է առաջինը արթնանում, քանի որ դա կարող է լինել այս գործընթացներից որևէ մեկը։ Ըստ էության, մենք ունեինք ժամանակացույց, որն ասում էր, որ այժմ կարող ենք արթնացնել այս գործընթացներից որևէ մեկը: Մենք պարզապես ընտրում ենք մեկը պատահականության սկզբունքով: Այսպիսով, երկուսն էլ պետք է նշել, քանի որ մենք կարող ենք արթնացնել նրանցից որևէ մեկին:

Եվ խնդիրն այն է, որ մենք ունենք CP-անսահմանություն: Եվ հետևաբար, միանգամայն հավանական է, որ մենք կարող ենք արթնացնել ավելի ուշ: Եվ եթե, օրինակ, մենք արթնացնենք ավելի ուշ, մենք կսպասենք նրան, ով հենց նոր է ստացել արգելափակումը, այնպես որ մենք չենք որոշում, թե կոնկրետ ով է արթնանալու առաջինը: Մենք պարզապես ստեղծում ենք նման իրավիճակ, և համակարգը նրանց կարթնացնելու է պատահական կարգով։

Կա հոդվածներ Եգոր Ռոգովի կողպեքների մասին. Տեսեք, դրանք նույնպես հետաքրքիր են և օգտակար։ Թեման, իհարկե, ահավոր բարդ է։ Շատ շնորհակալ եմ, Բրյուս:

Source: www.habr.com

Добавить комментарий