Unlocking the Postgres Lock Manager. Брус Момжыян

Расшыфроўка даклада 2020 года Бруса Мамжыяна "Unlocking the Postgres Lock Manager".

Unlocking the Postgres Lock Manager. Брус Момжыян

(Заўвага: Усе SQL запыты са слайдаў вы можаце атрымаць па гэтай спасылцы: http://momjian.us/main/writings/pgsql/locking.sql)

Прывітанне! Выдатна зноў быць тут у Расіі. Я прашу прабачэнне, што я не змог прыехаць у мінулым годзе, але сёлета ў Івана і ў мяне вялікія планы. Я, спадзяюся, што буду тут значна гушчару. Я люблю прыязджаць у Расію. Я буду наведваць Цюмень, Цвер. Я вельмі рады, што мне ўдасца пабываць у гэтых гарадах.

Мяне клічуць Брус Мамжыян. Я працую ў EnterpriseDB і працую з Postgres больш за 23 гадоў. Я жыву ў Філадэльфіі, у ЗША. Падарожнічаю прыкладна 90 дзён у годзе. І наведваю каля 40 канферэнцый. Мой вэб сайт, які змяшчае слайды, якія я вам буду зараз паказваць. Таму пасля канферэнцыі вы можаце з майго асабістага сайта іх спампаваць. Там таксама змяшчаюцца каля 30 прэзентацый. А таксама ёсць відэа і вялікая колькасць запісаў у блогу, больш за 500. Гэта дастаткова змястоўны рэсурс. І калі вам цікавы гэты матэрыял, то я вас запрашаю ім скарыстацца.

Я раней быў выкладчыкам, прафесарам да таго, як пачаў працаваць з Postgres. І я вельмі рады, што мне ўдасца зараз расказаць вам тое, што я збіраюся вам расказаць. Гэта адна з самых цікавых маіх прэзентацый. І гэтая прэзентацыя змяшчае 110 слайдаў. Казаць мы пачнем з простых рэчаў, а да канца даклад стане ўсё складаней і складаней, і стане дастаткова складаным.

Unlocking the Postgres Lock Manager. Брус Момжыян

Гэта даволі непрыемная размова. Блакаванне - гэта не самы папулярны прадмет. Мы жадаем, каб гэта кудысьці знікла. Гэта як хадзіць да стаматолага.

Unlocking the Postgres Lock Manager. Брус Момжыян

  1. Блакаванне з'яўляецца праблемай для вялікай колькасці людзей, якія працуюць у базах даных і ў якіх працуюць адначасова некалькі працэсаў. Ім неабходна блакіроўка. Т. е. сёння я вам дам базавыя веды па блакаванні.
  2. Ідэнтыфікатары транзакцый. Гэта даволі сумная частка прэзентацыі, але іх трэба зразумець.
  3. Далей мы пагаворым аб тыпах блакіроўкі. Гэта дастаткова механічная частка.
  4. І далей мы прывядзем некаторыя прыклады блакіровак. І гэта будзе дастаткова складана для ўспрымання.

Unlocking the Postgres Lock Manager. Брус Момжыян

Давайце пагаворым аб блакіроўках.

Unlocking the Postgres Lock Manager. Брус Момжыян

Тэрміналогія ў нас дастаткова складаная. Колькі з вас ведаюць, адкуль гэты ўрывак? Два чалавекі. Гэта з гульні, якая называецца «Каласальная прыгода ў пячоры». Гэта была тэкставая кампутарная гульня ў 80-ых гадах, мне падаецца. Там трэба было зайсці ў пячору, у лабірынт і тэкст мяняўся, але пры гэтым змест быў прыкладна аднолькавы кожны раз. Вось так я памятаю гэтую гульню.

Unlocking the Postgres Lock Manager. Брус Момжыян

І тут мы бачым найменне блакіровак, якія дашлі да нас з Oracle. Мы выкарыстоўваем іх.

Unlocking the Postgres Lock Manager. Брус Момжыян

Тут мы бачым тэрміны, якія мяне бянтэжаць. Напрыклад, SHARE UPDATE ECXLUSIVE. Далей SHARE RAW ECXLUSIVE. Сапраўды кажучы, гэтыя назовы не вельмі зразумелыя. Мы пастараемся іх больш дэталёва разгледзець. Некаторыя змяшчаюць слова "share", якое значыць - аддзяліцца. Некаторыя змяшчаюць слова «exclusive» - эксклюзіўны. У некаторых змяшчаюцца абодва гэтыя словы. Я б хацеў пачаць з таго, як гэтыя блакіроўкі працуюць.

Unlocking the Postgres Lock Manager. Брус Момжыян

І таксама вельмі важнае слова "доступ" - access. І словы "row" - радок. Т. е. размеркаванне доступу, размеркаванне радкоў.

Unlocking the Postgres Lock Manager. Брус Момжыян

Яшчэ адна праблема, якую неабходна зразумець у Postgres, я, нажаль, не змагу распавесці пра яе ў сваім выступе, гэта MVCC. У мяне ёсць асобная прэзентацыя па гэтай тэме на маім вэб-сайце. І калі вы думаеце, што гэтая прэзентацыя складаная, то MVCC - гэта, напэўна, мая самая складаная. І калі вам цікава, то можаце паглядзець яе на сайце. Паглядзець можаце відэа.

Unlocking the Postgres Lock Manager. Брус Момжыян

Яшчэ адзін момант, які нам неабходна зразумець - гэта ідэнтыфікатары транзакцыі. Многія транзакцыі не могуць працаваць без унікальных ідэнтыфікатараў. І тут у нас ідзе тлумачэнне таго, што такое транзакцыя. У Postgres ёсць дзве сістэмы нумарацыі транзакцый. Я ведаю, гэтае не вельмі прыгожае рашэнне.

Unlocking the Postgres Lock Manager. Брус Момжыян

Таксама майце на ўвазе, што слайды будуць дастаткова складаныя для ўспрымання, таму на тое, што выдзелена чырвоным колерам, менавіта на гэта трэба звярнуць увагу.

Unlocking the Postgres Lock Manager. Брус Момжыян

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

Глядзім. Чырвоным колерам выдзелены нумар транзакцыі. Тут паказана функцыя SELECT pg_back. Яна вяртае маю транзакцыю і ID гэтай транзакцыі.

Яшчэ адзін момант, калі вам падабаецца гэтая прэзентацыя і вы жадаеце запусціць яе ў сваёй базе дадзеных, тыя вы можаце прайсці па гэтай спасылцы, выдзеленай ружовым колерам, і спампаваць SQL для гэтай прэзентацыі. І можаце проста запусціць яе ў вашым PSQL і ўся прэзентацыя апынецца ў вас на экране неадкладна. Яна не будзе змяшчаць кветак, але прынамсі мы зможаце яе ўбачыць.

Unlocking the Postgres Lock Manager. Брус Момжыян

У дадзеным выпадку мы бачым ID транзакцыі. Гэта нумар, які мы ёй прысвоілі. І ёсць яшчэ адзін тып ID транзакцыі ў Postgres, які называецца віртуальны ID транзакцыя

І мы павінны зразумець гэта. Гэта вельмі важна, інакш мы не зможам зразумець блакаванне ў Postgres.

Віртуальны ID транзакцыя - гэта ID транзакцыі, якая не ўтрымлівае пастаянных значэнняў. Напрыклад, калі я запускаю каманду SELECT, то я, хутчэй за ўсё, не буду мяняць базу дадзеных, я нічога не буду блакаваць. Таму, калі мы запускаем просты SELECT, мы не даем гэтай транзакцыі пастаянны ID. Мы там даём ёй толькі віртуальны ID.

І гэта павялічвае прадукцыйнасць Postgres, паляпшае магчымасці для ачысткі, таму віртуальны ID транзакцыі складаецца з двух лікаў. Першы лік перад слэшам - гэта ID бэкенда. А справа мы бачым проста лічыльнік.

Unlocking the Postgres Lock Manager. Брус Момжыян

Таму калі запускаю запыт, то ён кажа, што ID бэкэнд - 2.

Unlocking the Postgres Lock Manager. Брус Момжыян

А калі я запускаю серыю такіх транзакцый, то мы бачым, што лічыльнік кожны раз павялічваецца, калі я запускаю запыт. Напрыклад, калі я запускаю запыт 2/10, 2/11, 2/12 і т. д.

Unlocking the Postgres Lock Manager. Брус Момжыян

Майце на ўвазе, што тут ёсць дзве калонкі. Злева мы бачым віртуальны ID транзакцыі - 2/12. А справа ў нас пастаянны ID транзакцыі. І гэтае поле пустое. І гэтая транзакцыя не мадыфікуе базу даных. Таму я не прысвойваю ёй пастаянны ID транзакцыі.

Unlocking the Postgres Lock Manager. Брус Момжыян

Як толькі я запускаю каманду аналізаваць ((ANALYZE)), то той жа самы запыт выдае мне пастаянны ID транзакцыі. Паглядзіце, як у нас гэта змянілася. Раней у мяне не было гэтага ID, зараз з'явіўся.

Unlocking the Postgres Lock Manager. Брус Момжыян

Такім чынам, тут яшчэ адзін запыт, яшчэ адна транзакцыя. Віртуальны нумар транзакцыі - 2/13. І калі я папрашу пастаянны ID транзакцыі, то, калі я запушчу запыт, я яго атрымаю.

Unlocking the Postgres Lock Manager. Брус Момжыян

Такім чынам, яшчэ раз. У нас ёсць віртуальны ID транзакцыі і пастаянны ID транзакцыі. Проста зразумейце гэты момант, каб зразумець паводзіны Postgres.

Unlocking the Postgres Lock Manager. Брус Момжыян

Мы пераходзім да трэцяга падзелу. Тут мы проста пройдзем праз розныя тыпы блакіровак у Postgres. Гэта ня вельмі цікава. Апошні раздзел будзе значна цікавей. Але мы мусім разгледзець базавыя рэчы, таму інакш мы не зразумеем таго, што будзе далей.

Мы пройдзем праз гэты раздзел, мы паглядзім на кожны тып блакіровак. І я вам пакажу прыклады, як яны ўстанаўліваюцца, як яны працуюць, пакажу вам некаторыя запыты, якія можна выкарыстоўваць, каб паглядзець, як працуе блакіроўка ў Postgres.

Unlocking the Postgres Lock Manager. Брус Момжыян

Каб стварыць запыт і паглядзець, што адбываецца ў Postgres, нам трэба выпусціць запыт у system view. У дадзеным выпадку чырвоным колерам у нас выдзелены pg_lock. Pg_lock - гэта сістэмная табліца, якая кажа нам, якія блакіроўкі цяпер выкарыстоўваюцца ў Postgres.

Тым не менш, мне вельмі складана паказаць вам pg_lock сам па сабе, таму што гэта даволі складана. Таму я стварыў view, які паказвае pg_locks. І ён таксама выконвае для мяне некаторую працу, якая дазваляе мне лепей зразумець. Т. е. ён выключае мае блакаванні, маю ўласную сесію і г. д. Гэта проста стандартны SQL і ён дазваляе лепш вам паказаць, што адбываецца.

Unlocking the Postgres Lock Manager. Брус Момжыян

Яшчэ адна праблема ў тым, што гэты view вельмі шырокі, таму мне даводзіцца стварыць другі - lockview2.

Unlocking the Postgres Lock Manager. Брус Момжыян І ён паказвае мне яшчэ калонкі з табліцы. І яшчэ адзін, які паказвае мне астатнія калонкі. Гэта дастаткова складана, таму я пастараўся прадставіць гэта як мага прасцей.

Unlocking the Postgres Lock Manager. Брус Момжыян

Такім чынам, мы стварылі табліцу, якая называецца Lockdemo. І мы стварылі там адзін радок. Гэта наша ўзорная табліца. І мы будзем ствараць раздзелы, каб проста паказаць вам прыклады блакіровак.

Unlocking the Postgres Lock Manager. Брус Момжыян

Такім чынам, адзін радок, адна калонка. Першы тып блакавання называецца ACCESS SHARE. Гэта найменш забараняльная блакіроўка. Гэта азначае, што яна практычна не канфліктуе з астатнімі блакіроўкамі.

І калі мы жадаем экспліцытна вызначыць блакаванне, мы запускаем каманду «lock table». І яна відавочна заблакуе, т. е. у рэжыме ACCESS SHARE мы запускаем lock table. І калі я запушчу PSQL у фонавым рэжыме, то я запускаю такім чынам другую сесію з маёй першай сесіі. Т. е. што я зраблю тут? Я пераходжу да іншай сесіі і кажу ёй "пакажы мне lockview для дадзенага запыту". І тут у мяне AccessShareLock у гэтай табліцы. Гэта якраз тое, што я запытваў. І ён кажа, што блакіроўка была прысвоена. Вельмі проста.

Unlocking the Postgres Lock Manager. Брус Момжыян

Далей, калі мы глядзім у другую калонку, то там нічога няма. Яны пустыя.

Unlocking the Postgres Lock Manager. Брус Момжыян

І калі я запускаю каманду "SELECT", то гэта імпліцытны (відавочны) спосаб запытаць AccessShareLock. Таму я выпускаю сваю табліцу і запускаю запыт і запыт вяртае некалькі радкоў. І ў адной з радкоў мы бачым AccessShareLock. Такім чынам SELECT выклікае AccessShareLock у табліцы. І ён не канфліктуе практычна ні з чым, таму што гэта блакаванне нізкага ўзроўню.

Unlocking the Postgres Lock Manager. Брус Момжыян

Што калі я запушчу SELECT і ў мяне будзе тры розныя табліцы? Раней я запускаў толькі адну табліцу, зараз я запускаю тры: pg_class, pg_namespace і pg_attribute.

Unlocking the Postgres Lock Manager. Брус Момжыян

І зараз, калі я гляджу на запыт, я бачу 9 AccessShareLocks у трох табліцах. Чаму? Сінім колерам выдзелена тры табліцы: pg_attribute, pg_class, pg_namespace. Але вы таксама можаце бачыць, што ўсе індэксы, якія вызначаны праз гэтыя табліцы таксама маюць AccessShareLock.

І гэта блакіроўка, якая практычна не канфліктуе з іншымі. А ўсё, што яна робіць, гэта проста не дае нам скінуць табліцу, пакуль мы яе выбіраем. Гэта мае сэнс. Т. е. калі мы выбіраем табліцу, яна ў гэты момант знікае, то гэта няправільна, таму AccessShare - гэта блакіроўка нізкага ўзроўню, якая кажа нам "не выдаляйце гэтую табліцу, пакуль я працую". Па сутнасці, гэта ўсё, што яна робіць.

Unlocking the Postgres Lock Manager. Брус Момжыян

ROW SHARE - гэта блакіроўка трохі адрозніваецца.

Unlocking the Postgres Lock Manager. Брус Момжыян

Возьмем прыклад. SELECT ROW SHARE спосаб блакавання кожнага радка па асобнасці. Такім чынам, ніхто не можа выдаліць іх ці змяніць іх, пакуль мы іх глядзім.

Unlocking the Postgres Lock Manager. Брус МомжыянТакім чынам, тое, што робіць SHARE LOCK? Мы бачым, што ID транзакцыі 681 для SELECT'а. І гэта цікава. Што тут у нас адбылося? Першы раз мы бачым нумар у полі "Lock". Мы бярэм ID транзакцыі, і ён кажа, што блакуе яе ў эксклюзіўным рэжыме. Усё, што ён робіць, ён кажа, што ў мяне ёсць радок, які тэхнічна заблакаваны недзе ў табліцы. Але не гаворыць, дзе канкрэтна. Крыху пазней мы больш падрабязна гэта разгледзім.

Unlocking the Postgres Lock Manager. Брус Момжыян

Тут мы гаворым, што блакіроўка выкарыстоўваецца намі.

Unlocking the Postgres Lock Manager. Брус Момжыян

Такім чынам, эксклюзіўнае блакаванне экспліцытна(яўна) кажа, што яна эксклюзіўная. І таксама калі вы выдаляеце радок у гэтай табліцы, тое гэта і адбудзецца, як вы можаце бачыць.

Unlocking the Postgres Lock Manager. Брус Момжыян

SHARE EXCLUSIVE - гэта даўжэйшае блакаванне.

Unlocking the Postgres Lock Manager. Брус Момжыян

Гэта (ANALYZE) каманда аналізатара, якая будзе выкарыстоўвацца.

Unlocking the Postgres Lock Manager. Брус Момжыян

SHARE LOCK - вы можаце экспліцытна заблакаваць у рэжыме share.

Unlocking the Postgres Lock Manager. Брус Момжыян

Вы можаце таксама стварыць унікальны індэкс. І там вы можаце ўбачыць SHARE LOCK, які з'яўляецца іх часткай. І ён блакуе табліцу і ўсталёўвае на яе блакаванне SHARE LOCK.

Па змаўчанні SHARE LOCK на табліцы азначае, што іншыя людзі могуць чытаць табліцу, але ніхто не можа яе мадыфікаваць. І менавіта гэта адбываецца, калі вы ствараеце ўнікальны азначнік.

Калі я ствараю ўнікальны concurrently індэкс, то ў мяне будзе іншы тып блакавання, таму што, як вы памятаеце, выкарыстанне concurrently індэксаў зніжае патрабаванне да блакіроўкі. І калі я выкарыстоўваю нармальнае блакаванне, нармальны індэкс, то я такім чынам прадухілю запіс у індэкс табліцы падчас яго стварэння. Калі я выкарыстоўваю concurrently індэкс, то мне трэба выкарыстоўваць іншы тып блакіроўкі.

Unlocking the Postgres Lock Manager. Брус Момжыян

SHARE ROW EXCLUSIVE - ізноў яе можна задаць экспліцытна (яўна).

Unlocking the Postgres Lock Manager. Брус Момжыян

Ці можам стварыць правіла, т. е. узяць нейкі вызначаны выпадак, пры якім яна будзе выкарыстоўвацца.

Unlocking the Postgres Lock Manager. Брус Момжыян

EXCLUSIVE блакіроўка азначае, што ніхто іншы мяняць табліцу не зможа.

Unlocking the Postgres Lock Manager. Брус Момжыян

Тут мы бачым розныя тыпы блакіровак.

Unlocking the Postgres Lock Manager. Брус Момжыян

ACCESS EXCLUSIVE, напрыклад, гэта каманда блакіроўкі. Напрыклад, калі вы робіце CLUSTER table, то гэта будзе азначаць, што ніхто не зможа запісваць туды. І яна блакуе не толькі саму табліцу, але і індэксы таксама.

Unlocking the Postgres Lock Manager. Брус Момжыян

Гэта другая старонка блакавання ACCESS EXCLUSIVE, дзе мы бачым канкрэтна, што яна блакуе ў табліцы. Яна блакуе асобныя радкі табліцы, што дастаткова цікава.

Гэта ўся базавая інфармацыя, якую я хацеў даць. Мы казалі пра блакіроўкі, пра ID транзакцый, казалі пра віртуальныя ID транзакцый, пра сталыя ID транзакцый.

Unlocking the Postgres Lock Manager. Брус Момжыян

І зараз мы пройдземся па прыкладах блакіровак. Гэта самая цікавая частка. Мы паглядзім вельмі цікавыя выпадкі. І мая задача ў гэтай прэзентацыі - даць вам лепшае ўяўленне аб тым, што Postgres на самой справе робіць, калі ён спрабуе блакаваць тыя ці іншыя рэчы. Мне падаецца, што ён вельмі добра ўмее блакаваць асобныя часткі.

Давайце разгледзім пэўныя прыклады.

Unlocking the Postgres Lock Manager. Брус Момжыян

Мы пачнем з табліц і з аднаго радка ў табліцы. Калі я ўстаўляю нешта, у мяне адлюстроўваецца ExclusiveLock, ID транзакцыі і ExclusiveLock на табліцы.

Unlocking the Postgres Lock Manager. Брус Момжыян

А што будзе, калі я ўстаўлю яшчэ два рады? І зараз у нашай табліцы тры рады. І я ўставіў адзін шэраг і атрымаў вось гэта на выхадзе. І калі я ўстаўляю яшчэ два рады, што тут дзіўнага? Тут ёсць дзівацтва, таму што я дадаў тры рады да гэтай табліцы, але ў мяне ўсё яшчэ два рады ў табліцы блакавання. І гэта, у сутнасці, асноватворныя паводзіны Postgres.

Многія думаю, што калі ў базе дадзеных, вы блакуеце 100 шэрагаў, то вам будзе неабходна стварыць 100 уводаў блакіровак. Калі я буду блакаваць адразу 1 шэрагаў, то тады мне патрэбна будзе 000 такіх запытаў. І калі мне трэба мільён ці мільярд заблакаваць. Але калі мы так будзем рабіць, то гэта будзе ня надта добра працаваць. Калі вы выкарыстоўвалі сістэму, якая стварае ўводы блакіроўкі для кожнага асобнага шэрагу, тыя вы бачыце, што гэта складана. Таму што вам трэба вызначыць адразу табліцу блакіроўкі, якая можа перапоўніцца, але Postgres так ня робіць.

І на гэтым слайдзе вельмі важна, што тут відавочна дэманструецца, што ёсць яшчэ адна сістэма, якая працуе ўсярэдзіне MVCC, якая блакуе асобныя радкі. Таму, калі вы блакуеце мільярды шэрагаў, то Postgres не стварае мільярд асобных каманд на блакіроўку. І гэта вельмі добра адбіваецца на прадукцыйнасці.

Unlocking the Postgres Lock Manager. Брус Момжыян

А як наконт абнаўлення? Я зараз абнаўляю шэраг, і вы можаце заўважыць, што ён адразу выканаў дзве розныя аперацыі. Ён адначасова заблакаваў табліцу, але ён таксама заблакаваў азначнік. І яму трэба было блакаваць азначнік, таму што ёсць унікальныя абмежаванні на гэтай табліцы. І мы хочам пераканацца, што ніхто яго не мяняе, таму мы яго блакуем.

Unlocking the Postgres Lock Manager. Брус Момжыян

А што будзе, калі я хачу абнавіць два рады? І мы бачым, што ён паводзіць сябе таксама. Мы праводзім у два разы больш абнаўленняў, але сапраўды такая ж колькасць радкоў блакіроўкі.

Калі вам цікава, як Postgres гэта робіць, вам трэба паслухаць мае выступы па MVCC, каб даведацца, як Postgres ўнутрана маркіруе гэтыя радкі, якія ён мяняе. І ў Postgres ёсць спосаб, пры дапамозе якога ён гэта робіць, але ён гэта не робіць на ўзроўні блакіроўкі табліц, ён робіць на ніжэйшым і на больш эфектыўным узроўні.

Unlocking the Postgres Lock Manager. Брус Момжыян

А калі я хачу нешта выдаліць? Калі я выдаляю, напрыклад, адзін шэраг і ў мяне ўсё яшчэ ёсць мае два ўступныя ў блакіроўкі, і нават калі я захачу выдаліць іх усе, то яны ўсё роўна там прысутнічаюць.

Unlocking the Postgres Lock Manager. Брус Момжыян

І, напрыклад, я хачу ўставіць 1 000 радкоў, а потым ці выдаліць, ці дадаць 1 000 радкоў, то тыя індывідуальныя радкі, якія я дадаю ці мяняю, яны не запісваюцца тут. Яны запісваюцца на ніжэйшым узроўні ўнутры самога шэрагу. І падчас выступу па MVCC я казаў пра гэта ў дэталях. Але вельмі важна, калі вы аналізуеце блакіроўкі, пераканацца, што ў вас блакіроўка на ўзроўні табліцы і што тут вы не бачыце, як вядзецца запіс асобных шэрагаў.

Unlocking the Postgres Lock Manager. Брус Момжыян

А як наконт экспліцытнай блакіроўкі?

Unlocking the Postgres Lock Manager. Брус Момжыян

Калі я націсну «абнавіць», то ў мяне ёсць два заблакаваныя шэрагі. І калі вылучу іх усё і націсну «абнавіць усюды», то ў мяне ўсё роўна застаюцца два запісы блакавання.

Unlocking the Postgres Lock Manager. Брус Момжыян

Мы не ствараем асобныя запісы на кожны асобны рад. Бо тады падае прадукцыйнасць, там можа быць гэтага зашмат. І мы можам аказацца ў непрыемнай сітуацыі.

Unlocking the Postgres Lock Manager. Брус Момжыян

І тое самае, калі мы робім shared, мы можам рабіць на ўсе 30 разоў.

Unlocking the Postgres Lock Manager. Брус Момжыян

Мы аднаўляем нашу табліцу, усё выдаляем, потым зноў устаўляемы адзін шэраг.

Unlocking the Postgres Lock Manager. Брус Момжыян

Яшчэ адзін від паводзін, які вы бачыце ў Postgres, гэта вельмі добра вядомыя і жаданыя паводзіны - гэта тое, што вы можаце праводзіць update або select. І вы можаце гэта рабіць адначасова. І select не блакуюць update і таксама самае ў зваротны бок. Мы кажам чытачу не блакаваць таго, хто піша, а той, хто піша, не блакаваў чытача.

Я пакажу вам прыклад гэтага. Я зраблю зараз выбар. Мы потым зробім INSERT. І вы потым зможаце ўбачыць - 694. Вы зможаце ўбачыць ID транзакцыі, якая правяла гэтую ўстаўку. І гэта тое, як гэта працуе.

Unlocking the Postgres Lock Manager. Брус Момжыян

І калі я зараз пагляджу на свой бэкэнд ID, то ён стаў - 695.

Unlocking the Postgres Lock Manager. Брус Момжыян

І я магу ўбачыць, што 695 з'яўляецца ў маёй табліцы.

Unlocking the Postgres Lock Manager. Брус Момжыян

І калі я праводжу абнаўленне тут вось так, то я атрымліваю іншы кейс. У гэтым выпадку 695 эксклюзіўнае блакіроўка, а ў update такія ж паводзіны, але паміж імі не ўзнікае канфлікту, што досыць незвычайна.

І вы можаце заўважыць, што на версе - гэта ShareLock, а ўнізе - гэта ExclusiveLock. І абедзве транзакцыі атрымаліся.

І трэба паслухаць мой выступ у MVCC, каб зразумець, як гэта адбываецца. Але гэта ілюстрацыя таго, што вы можаце рабіць гэта адначасова, г. зн. адначасова рабіць SELECT і UPDATE.

Unlocking the Postgres Lock Manager. Брус Момжыян

Давайце мы скінем і яшчэ раз зробім адну аперацыю.

Unlocking the Postgres Lock Manager. Брус Момжыян

Калі вы паспрабуеце запусціць адначасова два update на адным і тым жа шэрагу, тое яно заблакуецца. І памятайце, я казаў, што які чытае не блакуе пісьменніка, а пісьменнік чытача, але адзін пісьменнік блакуе іншага пісьменніка. Т. е. мы не можам рабіць так, каб два чалавекі адначасова абнаўлялі адзін і той жа шэраг. Трэба чакаць, пакуль адзін зь іх скончыць.

Unlocking the Postgres Lock Manager. Брус Момжыян

І для таго, каб гэта праілюстраваць, я пагляджу на Lockdemo табліцу. І мы паглядзім на адзін рад. На транзакцыю 698.

Мы гэта абнавілі да 2-х. 699 - гэта першае абнаўленне. І яно прайшло паспяхова ці яно знаходзіцца ў чакаючай транзакцыі і чакае, калі мы пацвердзім ці адменім.

Unlocking the Postgres Lock Manager. Брус Момжыян

Але паглядзіце на іншае - 2/51 - гэта наша першая транзакцыя, наша першая сесія. 3/112 - гэта другі запыт, які з'явіўся зверху і які змяніў гэтае значэнне на 3. І калі вы заўважыце, то верхні заблакаваў сам сябе, які 699. Але 3/112 не падалі блакіроўку. У калонцы Lock_mode напісана, што ён чакае. Ён чакае 699. І калі вы паглядзіце, дзе 699, ён вышэйшы. І што зрабіла першая сэсія? Яна стварыла эксклюзіўную блакіроўку на сваім уласным транзакцыйным ID. Гэта тое, як Postgres гэта робіць. Ён блакуе ўласны транзакцыйны ID. І калі вы хочаце чакаць, пакуль нехта пацвердзіць або адменіць, то трэба чакаць, пакуль ёсць транзакцыя. І таму мы можам убачыць дзіўны радок.

Давайце паглядзім яшчэ раз. Злева мы бачым наша працэсінгавае ID. У другой калонцы мы бачым наш віртуальны ID транзакцыі, а ў трэцяй бачым lock_type. Што гэта азначае? Па сутнасці, яна кажа, што блакуе транзакцыйны ID. Але заўважце, што ва ўсіх шэрагах унізе напісана relation. І таму ў вас два віды блакіроўкі ў табліцы. Ёсць блакіроўка relation. А таксама ёсць блакіроўка transactionid, дзе вы мы блакуеце самастойна, гэта менавіта тое, што адбываецца на першым шэрагу ці ў самым нізе, дзе transationid, дзе мы чакаем, каб 699 скончыў сваю аперацыю.

Я гляджу, што тут атрымоўваецца. І тут адначасова адбываюцца дзве рэчы. Вы гледзіце на блакіроўку па транзакцыйным ID у першым шэрагу, якая блакуе сама сябе. І яна блакуе сама сябе, каб прымусіць людзей чакаць.

Калі вы паглядзіце на 6-ы радок, то той жа запіс, што і першы. І таму транзакцыя 699 блакіруецца. 700 таксама самаблакуецца. І потым у ніжнім шэрагу вы ўбачыце, што мы чакаем, калі 699 скончыць сваю аперацыю.

Unlocking the Postgres Lock Manager. Брус Момжыян

І ў lock_type, tuple вы бачыце лікі.

Unlocking the Postgres Lock Manager. Брус Момжыян

Вы можаце ўбачыць, што гэта 0/10. І гэта нумар старонкі, і таксама offset гэтага канкрэтнага шэрагу.

Unlocking the Postgres Lock Manager. Брус Момжыян

І вы бачыце, што становіцца 0/11, калі мы абнаўляем.

Unlocking the Postgres Lock Manager. Брус Момжыян

Але насамрэч - гэта 0/10, таму што адбываецца чаканне гэтай аперацыі. Мы маем магчымасць паглядзець, што гэта той шэраг, які я чакаю, каб пацвердзіць.

Unlocking the Postgres Lock Manager. Брус Момжыян

Як толькі мы яго пацвердзілі і націснулі commit, і калі абнаўленне скончылася, гэта тое, што мы атрымліваем зноў. Транзакцыя 700 - гэта адзіная блакіроўка, яна больш нікога не чакае, таму што яе закамміцілі. Яна проста чакае, каб транзакцыя завяршылася. Як толькі 699 заканчваецца, мы больш нічога не чакаем. І зараз транзакцыя 700 кажа, што ўсё добра, што ўсе блакаванні, якія патрэбныя, у яе ёсць ва ўсіх дазволеных табліцах.

Unlocking the Postgres Lock Manager. Брус Момжыян

І каб яшчэ ўскладніць усю гэтую справу, мы ствараем яшчэ адзін view, які ў гэты раз нам прадаставіць іерархію. Я не чакаю, што вы зразумееце гэты запыт. Але гэта дасць нам больш ясны від таго, што адбываецца.

Unlocking the Postgres Lock Manager. Брус Момжыян

Гэта рэкурсіўны від, у якога таксама ёсць яшчэ адна секцыя. І яно потым зноў вяртае ўсё разам. Давайце выкарыстоўваць гэта.

Unlocking the Postgres Lock Manager. Брус Момжыян

Што, калі мы зробім тры адначасовыя абнаўленні і скажам, што шэраг зараз роўны тром. І мы памяняем 3 на 4.

Unlocking the Postgres Lock Manager. Брус Момжыян

І вось мы бачым 4. І транзакцыйны ID 702.

Unlocking the Postgres Lock Manager. Брус Момжыян

І затым я памяняю 4 на 5. А 5 на 6, а 6 на 7. І я выбудоўваю ў чаргу шэраг людзей, якія будуць чакаць таго, каб гэтая адна транзакцыя скончылася.

Unlocking the Postgres Lock Manager. Брус Момжыян

І ўсё становіцца зразумелым. Які першы шэраг? Гэта 702. Гэта транзакцыйны ID, які першапачаткова задаў гэтае значэнне. А што ў мяне напісана ў калонцы Granted? У мяне ёсць адзнакі f. Гэта тыя мае абнаўленні, якія (5, 6, 7) не могуць быць ухваленыя, таму што мы чакаем, каб транзакцыйны ID 702 скончыўся. Там у нас ёсць блакіроўка транзакцыйнага ID. І атрымліваецца 5 транзакцыйных блакіровак ID.

І калі вы паглядзіце на 704, на 705, то там яшчэ нічога не напісана, бо яны яшчэ ня ведаюць, што адбываецца. Яны проста пішуць, што без уяўлення, што адбываецца. І яны проста сыдуць у сон, таму што яны чакаюць, пакуль нехта скончыць і іх разбудзяць, калі з'явіцца магчымасць памяняць шэраг.

Unlocking the Postgres Lock Manager. Брус Момжыян

Гэта тое, як гэта выглядае. Зразумела, што яны ўсё чакаюць 12-ы радок.

Unlocking the Postgres Lock Manager. Брус Момжыян

Гэта тое, што мы бачылі вось тут. Вось 0/12.

Unlocking the Postgres Lock Manager. Брус Момжыян

Такім чынам, як толькі першая транзакцыя ўхвалена, тыя вы можаце тут убачыць, як працуе іерархія. І зараз становіцца ўсё ясна. Яны ўсё становяцца чыстымі. І яны на самой справе ўсё яшчэ ў чаканні.

Unlocking the Postgres Lock Manager. Брус Момжыян

Вось што адбываецца. 702 коммітуецца. І зараз 703 атрымлівае гэтае блакаванне шэрагу, а потым 704 пачынае чакаць, калі 703 закоммитется. І 705 таксама гэтага чакае. І калі ўсё гэта завяршаецца, то яны самі сябе зачышчаюць. І я хацеў бы ўказаць на тое, што ўсе выстройваюцца ў чаргу. І гэта вельмі падобна на сітуацыю з коркам, калі ўсё чакаюць першую машыну. Першая машына спынілася, і ўсе выстройваюцца ў доўгую лінію. Потым яна рухаецца, потым наступная машына можа праехаць наперад і атрымаць сваё блакаванне і г.д.

Unlocking the Postgres Lock Manager. Брус Момжыян

І калі вам гэта падалося недастаткова складаным, то мы зараз пагаворым з вамі аб deadlocks. Я не ведаю, хто з вас сутыкаўся з імі. Гэта дастаткова распаўсюджаная праблема ў сістэмах баз дадзеных. Але deadlocks - гэта той выпадак, калі адна сесія чакае, каб нешта выканала іншая сесія. А ў гэты момант іншая сэсія чакае, каб першая сэсія выканала нешта.

І, напрыклад, калі Іван кажа: "Дай мне што-небудзь", а я кажу: "Не, я табе гэта дам толькі, калі ты мне дасі нешта іншае". А ён кажа: "Не, я не дам табе гэта, калі ты мне не дасі". І мы атрымліваемся ў сітуацыі мёртвай блакіроўкі. Я ўпэўнены, што Іван так не зробіць, але вы разумееце сэнс, што ў нас два чалавекі хочуць нешта атрымаць і яны не гатовы гэта аддаць, пакуль іншы чалавек ім не аддасць, тое, што яны хочуць. І тут няма рашэньня.

І, па сутнасці, вашай базе даных трэба гэта выяўляць. І затым неабходна выдаляць або зачыняць адну з сесій, таму што ў адваротным выпадку яны там застануцца назаўжды. І мы гэта бачым у базах даных, мы гэта бачым у аперацыйных сістэмах. І ва ўсіх месцах, дзе ў нас ёсць паралельныя працэсы, такое можа быць.

Unlocking the Postgres Lock Manager. Брус Момжыян

І мы паставім зараз дзве deadlocks. Мы паставім 50 і 80. У першы шэраг я правяду абнаўленне з 50 на 50. У мяне атрымаецца нумар транзакцыі 710.

Unlocking the Postgres Lock Manager. Брус Момжыян

І затым я памяняю 80 на 81, і 50 на 51.

Unlocking the Postgres Lock Manager. Брус Момжыян

І вось, як гэта будзе выглядаць. І таму ў 710 ёсць блакіроўка шэрагу, а 711 чакае пацверджанне. Мы бачылі гэта, калі абнаўлялі. 710 - з'яўляецца ўладальнікам нашага шэрагу. А 711 чакае, каб 710 скончыў транзакцыю.

Unlocking the Postgres Lock Manager. Брус Момжыян

І там нават напісана на якім менавіта шэрагу ў нас адбываецца deadlocks. І вось дзе гэта пачынае становіцца дзіўным.

Unlocking the Postgres Lock Manager. Брус Момжыян

Цяпер мы абнаўляем 80 на 80.

Unlocking the Postgres Lock Manager. Брус Момжыян

І вось, дзе пачынаецца deadlocks. 710 чакае водгуку ад 711, а 711 чакае 710. І гэта нядобра скончыцца. І з гэтага няма выйсця. І яны будуць чакаць водгуку адзін ад аднаго.

Unlocking the Postgres Lock Manager. Брус Момжыян

І гэта проста ўсё пачне затрымліваць. І мы гэтага не жадаем.

Unlocking the Postgres Lock Manager. Брус Момжыян

І ў Postgres ёсць спосабы заўважаць, калі гэта адбываецца. І калі гэта адбываецца, то вы атрымліваеце вось такую ​​памылку. І з гэтага ясна, што вось такі працэс чакае SHARE LOCK'а ад іншага працэсу, т. е. які блакуецца 711 працэсам. А той працэс чакаў, каб быў дадзены SHARE LOCK на вось такі транзакцыйны ID і быў заблакаваны такім-то працэсам. Таму тут сітуацыя мёртвай блакіроўкі.

Unlocking the Postgres Lock Manager. Брус Момжыян

А ці бывае трохбаковы deadlocks? Ці магчыма гэта? Так.

Unlocking the Postgres Lock Manager. Брус Момжыян

Мы забіваем гэтыя лікі ў табліцу. Мы мяняем 40 на 40, мы робім блакіроўку.

Unlocking the Postgres Lock Manager. Брус Момжыян

Мяняем 60 на 61, 80 на 81.

Unlocking the Postgres Lock Manager. Брус Момжыян

А затым мы мяняем 80, а затым - бум!

Unlocking the Postgres Lock Manager. Брус Момжыян

І 714 цяпер чакае 715. 716-ты 715-га чакае. І з гэтым ужо нічога не зрабіць.

Unlocking the Postgres Lock Manager. Брус Момжыян

Тут ужо не два чалавекі, тут ужо тры чалавекі. Я хачу нешта ад цябе, гэты жадае нешта ад трэцяга чалавека, а трэці чалавек жадае нешта ад мяне. І мы атрымліваемся ў трохбаковым чаканні, таму што мы ўсё чакаем, пакуль іншы чалавек завершыць тое, што ён павінен зрабіць.

Unlocking the Postgres Lock Manager. Брус Момжыян

І Postgres ведае, на якім шэрагу гэта адбываецца. І таму ён выдасць вам наступнае паведамленне, якое паказвае, што ў вас ёсць праблема, дзе тры уступных блакуюць адзін аднаго. І тут няма абмежаванняў. Гэта можа быць у выпадку, дзе 20 запісаў блакуюць адзін аднаго.

Unlocking the Postgres Lock Manager. Брус Момжыян

Наступная праблема - гэта serializable.

Unlocking the Postgres Lock Manager. Брус Момжыян

Калі спецыяльная serializable блакіроўка.

Unlocking the Postgres Lock Manager. Брус Момжыян

І вяртаемся да 719. У яго суцэль нармальная выдача.

Unlocking the Postgres Lock Manager. Брус Момжыян

І вы можаце націснуць, каб зрабіць транзакцыю са serializable.

Unlocking the Postgres Lock Manager. Брус Момжыян

І вы разумееце, што ў вас зараз ёсць іншы від блакавання SA - гэта азначае serializable.

Unlocking the Postgres Lock Manager. Брус Момжыян

Unlocking the Postgres Lock Manager. Брус Момжыян

І таму ў нас ёсць новы від блакіроўкі, які называецца SARieadLock, які з'яўляецца серыйнай блакіроўкай і дазваляе ўводзіць серыйнікі.

Unlocking the Postgres Lock Manager. Брус Момжыян

І таксама вы можаце ўстаўляць унікальныя індэксы.

Unlocking the Postgres Lock Manager. Брус Момжыян

У гэтай табліцы ў нас ёсць унікальныя індэксы.

Unlocking the Postgres Lock Manager. Брус Момжыян

Таму, калі я сюды ўвяду лік 2, таму ў мяне ёсць 2. Але ў самым уверсе я ўстаўляю яшчэ адно 2. І вы можаце бачыць, што ў 721-го эксклюзіўнае блакаванне. Але зараз 722 чакае, каб 721 завяршыў сваю аперацыю, таму што ён не можа ўставіць 2 да таго часу, пакуль не ведае, што адбудзецца з 721.

Unlocking the Postgres Lock Manager. Брус Момжыян

І калі мы робім subtransaction.

Unlocking the Postgres Lock Manager. Брус Момжыян

Вось у нас 723.

Unlocking the Postgres Lock Manager. Брус Момжыян

І калі мы захоўваем кропку і потым яе абнаўляем, то ў нас атрымліваецца новы транзакцыйны ID. Гэта яшчэ адзін характар ​​паводзін, якія вам трэба ведаць. Калі мы гэта вяртаем, то транзакцыйны ID сыходзіць. 724 сыходзіць. Але зараз у нас з'яўляецца 725.

І што я спрабую тут зрабіць? Я спрабую паказаць вам прыклады незвычайных блакіровак, якія вы можаце знайсці: няхай гэта будзе serializable блакіроўкі або SAVEPOINT - гэта розныя віды блакіровак, якія будуць з'яўляцца ў табліцы блакіровак.

Unlocking the Postgres Lock Manager. Брус Момжыян

Гэта стварэнне экспліцытных (яўных) блакіровак, у якіх pg_advisory_lock.

Unlocking the Postgres Lock Manager. Брус Момжыян

І вы бачыце, што тып блакавання тут лічыцца як advisory. І тут чырвоным напісана "advisory". І вы можаце адначасова так заблакаваць з pg_advisory_unlock.

Unlocking the Postgres Lock Manager. Брус Момжыян

І завяршаючы я хацеў бы вам паказаць яшчэ адну крышеносную рэч. Я ствару яшчэ адзін выгляд. Але я злучу табліцу pg_locks з табліцай pg_stat_activity. І навошта я хачу гэта зрабіць? Таму што гэта дазволіць мне паглядзець і ўбачыць усе бягучыя сесій і ўбачыць, якіх менавіта блакіровак яны чакаюць. І гэта досыць цікава, калі мы збіраем разам табліцу блакіровак і табліцу запытаў.

Unlocking the Postgres Lock Manager. Брус Момжыян

І тут мы ствараем pg_stat_view.

Unlocking the Postgres Lock Manager. Брус Момжыян

І мы абнаўляем шэраг на адзін. І тут мы бачым 724. А затым мы абнаўляем наш шэраг да трох. І што вы бачыце тут зараз? Гэта запыты, г. зн. вы бачыце ўвесь спіс запытаў, якія пералічаны ў левай калонцы. А затым на правым баку вы можаце бачыць блакіроўкі і тое, што яны ствараюць. І гэта можа быць больш зразумела для вас, каб вам не было патрэбы кожны раз вяртацца да кожнай сесіі і глядзець - ці трэба да яе далучыцца ці не. За нас гэта робяць.

Яшчэ адна функцыя, якая вельмі карысная - гэта pg_blocking_pids. Вы, мусіць, пра яе не чулі ніколі. Што яна робіць? Яна дазваляе нам сказаць, што для гэтай сесіі 11740, якія менавіта ID-працэсаў яна чакае. І вы можаце бачыць, што 11740 чакае 724. І 724 знаходзіцца на самым версе. А 11306 з'яўляецца вашым ID-працэсам. Па сутнасці, гэтая функцыя ідзе па вашай табліцы блакіровак. І я ведаю, што гэта крыху складана, але ў вас атрымліваецца гэта разумець. Па сутнасці, гэтая функцыя праходзіць праз гэтую табліцу блакіровак і спрабуе знайсці, дзе гэты працэс ID, улічваючы тыя блакіроўкі, якая яна чакае. І таксама спрабуе вылічыць, які менавіта працэс ID, у таго працэсу, які чакае блакіроўкі. Таму вы можаце запусціць гэтую функцыю pg_blocking_pids.

І гэта бывае вельмі карысна. Мы гэта дадалі толькі з версіі 9.6/5, таму гэтай функцыі ўсяго толькі XNUMX гадоў, але яна вельмі і вельмі карысная. І тое ж самае тычыцца другога запыту. Ён паказвае менавіта тое, што трэба бачыць.

Unlocking the Postgres Lock Manager. Брус Момжыян

Гэта тое, пра што я хацеў з вамі паразмаўляць. І як я чакаў, мы выкарыстоўвалі ўвесь наш час, таму што была такая вялікая колькасць слайдаў. І слайды даступныя для запампоўкі. Я хацеў бы падзякаваць вам за тое, што вы былі тут. Я ўпэўнены, што вам спадабаецца рэшта канферэнцыі, вялікі дзякуй!

пытанні:

Напрыклад, калі я імкнуся абнавіць радкі, а другая сесія імкнецца выдаліць усю табліцу. Наколькі я разумею, што там павінна быць нешта накшталт intent lock'а. Ці ёсць такое ў Postgres?

Unlocking the Postgres Lock Manager. Брус Момжыян

Вяртаемся да самага пачатку. Магчыма, вы памятаеце, што калі вы робіце што б там ні было, напрыклад, калі вы робіце SELECT, то мы выдаем AccessShareLock. І гэта прадухіляе выдаленне табліцы. Таму калі вы, напрыклад, жадаеце абнавіць шэраг у табліцы або выдаліць шэраг, то нехта не можа выдаліць усю табліцу адначасова з гэтым, таму што вы трымаецца гэты AccessShareLock над усёй табліцай і над побач. І як толькі вы скончылі, яны могуць гэта выдаліць. Але пакуль вы непасрэдна нешта там мяняеце, яны не змогуць зрабіць.

Давайце яшчэ раз. Давайце пяройдзем да прыкладу з выдаленнем. І вы бачыце, як на шэрагу ёсць эксклюзіўны lock над усёй табліцай.

Гэта будзе выглядаць як lock exclusive, правільна?

Так, гэта падобна на гэта. Я разумею, аб чым вы гаворыце. Вы кажаце, што, калі я выканаю SELECT, то ў мяне будзе ShareExclusive, а потым я перакладаю гэта ў стан Row Exclusive, то ці становіцца гэта праблемай? Але на дзіва гэта не стварае праблему. Гэта падобна на павелічэнне ступені блакавання, але, па сутнасці, у мяне есць lock, які прадухіляе выдаленне. І зараз, калі я раблю гэты замак больш магутным, то ён усё яшчэ прадухіляе выдаленне. Таму гэта не тое, каб я паднімаюся ўверх. Т. е. ён прадухіляў гэта і калі ён быў на больш нізкім узроўні, таму, калі я падвышаю яго ўзровень, ён усё яшчэ прадухіляе выдаленне табліцы.

Я разумею, аб чым вы гаворыце. Тут няма выпадку павелічэння ступені блакавання, дзе вы спрабуеце адмовіцца ад адной блакіроўкі, каб увесці больш магутную. Тут гэта проста паўсюдна павялічвае гэтае прадухіленне, таму гэта не выклікае ніякага канфлікту. Але гэта добрае пытаньне. Вялікі дзякуй, што яго задалі!

Што нам неабходна рабіць для таго, каб пазбегнуць сітуацыі deadlock'а, калі ў нас ёсць шмат сесій, вялікая колькасць карыстальнікаў?

Postgres аўтаматычна заўважае сітуацыі deadlock'а. І аўтаматычна будзе выдаляць адну з сесій. Адзіны спосаб, які дапаможа пазбегнуць сітуацыю з мёртвымі блакіроўкамі, калі будзеце блакаваць людзей у адным і тым жа парадку. Таму, калі вы паглядзіце на ваша прыкладанне, то часта прычына deadlocks… Давайце ўявім, што я хачу заблакаваць дзве розныя рэчы. Адно прыкладанне блакуе табліцу 1, а іншае прыкладанне блакуе 2, а затым табліцу 1. І самы просты спосаб пазбегнуць deadlocks - гэта паглядзець на ваша прыкладанне і паспрабаваць пераканацца ў тым, што блакіроўка адбываецца ў адной той жа чарговасці ва ўсіх прыкладаннях. І гэта, як правіла, прыбірае 80% праблем, таму што самыя розныя людзі пішуць гэтыя прыкладанні. І калі вы блакуеце іх у адным і тым жа парадку, тыя вы не сутыкаецеся з сітуацыяй deadlock'а.

Вялікі дзякуй за ваш выступ! Вы казалі аб vacuum full і, калі я правільна разумею, то vacuum full дэфармуе парадак запісаў у асобным захоўванні, таму захоўваюць бягучыя запісы нязменнымі. А чаму vacuum full бярэ доступ эксклюзіўнага блакавання і чаму ён канфліктуе з аперацыямі па запісе?

Гэта добрае пытанне. Чыннік складаецца ў тым, што vacuum full бярэ табліцу. І мы, па сутнасці, ствараем новую версію табліцы. І табліца будзе новай. Атрымліваецца гэта будзе зусім новая вэрсія табліцы. І праблема заключаецца ў тым, што, калі мы гэта робім, мы не жадаем, каб людзі чыталі гэта, таму што нам трэба, каб яны ўбачылі новую табліцу. І таму гэта злучаецца з папярэднім пытаннем. Калі б мы маглі адначасова чытаць, то мы б не здолелі яго перамясціць і накіроўваць людзей на новую табліцу. Нам трэба было б чакаць, каб кожны скончыў чытаць гэтую табліцу, і таму, па сутнасьці, гэта сытуацыя lock exclusive.
Мы проста кажам, што мы блакуем з самага пачатку, таму што мы ведаем, што ў самым канцы нам спатрэбіцца эксклюзіўнае блакіроўка для таго, каб перасунуць усіх на новую копію. Таму патэнцыйна мы можам гэта дазволіць. І мы так робім гэта з адначасовым індэксаваннем. Але гэта нашмат складаней зрабіць. І гэта вельмі моцна ставіцца да вашага папярэдняга пытання пра lock exclusive.

Ці магчыма дадаваць locking timeout у Postgres? У Oracle я магу, напрыклад, напісаць "абраць на абнаўленне" і чакаць 50 секунд да абнаўлення. Гэта было добра для дадатку. Але ў Postgres у мяне альбо трэба гэта рабіць адразу і зусім не чакаць, альбо чакаць да нейкага часу.

Так, вы можаце выбраць тайм-аўт на вашыя блакіроўкі, на вашыя locks. Вы таксама можаце выдаць каманду no way, якая будзе …, калі вы не зможаце адразу атрымаць блакаванне. Таму альбо lock timeout, альбо іншае, што дазволіць вам гэта зрабіць. Гэта не робіцца на сінтаксічным узроўні. Гэта робіцца, як зменная на сэрвэры. Часам гэта нельга выкарыстоўваць.

Вы можаце адкрыць 75 слайд?

Да.

Unlocking the Postgres Lock Manager. Брус Момжыян

І маё пытанне наступнае. Чаму абодва працэсу абнаўлення чакаюць 703?

І гэта цудоўнае пытанне. Я не разумею, дарэчы, чаму Postgres гэта робіць. Але калі 703 быў створаны, ён чакаў 702. І калі 704 і 705 з'яўляюцца, то здаецца, што яны не ведаюць таго, што яны чакаюць, бо там яшчэ нічога няма. І Postgres гэта робіць так: калі вы не можаце атрымаць блакіроўку, то ён піша "А сэнс вас апрацоўваць?", таму што вы і так чакаеце кагосьці. Таму проста дамо яму павісець у паветры, ён увогуле не абнаўляе гэта. Але што адбылося тут? Як толькі 702 завяршыў працэс і 703 атрымаў сваю блакіроўку, то сістэма вярнулася назад. І сказала, што зараз у нас ёсць два чалавекі, якія знаходзяцца ў чаканні. А затым давайце мы іх абновім разам. І пакажам, што абодва чакаюць.

Я ня ведаю, чаму Postgres так робіць. Але ёсць праблема, якая называецца f…. Мне здаецца, што гэта не тэрмін на рускай. Гэта калі ўсё чакаюць аднаго замка, нават калі ёсць 20 інстанцый, які чакаюць замка. І раптам яны ўсё прачынаюцца адначасова. І ўсё пачынаюць спрабаваць зрэагаваць. Але сістэма робіць так, што ўсё чакаюць 703. Таму што яны ўсё чакаюць, і мы іх адразу ўсіх выбудуем у чаргу. І калі з'яўляецца любы іншы новы запыт, які быў сфарміраваны пасля гэтага, напрыклад, 707, то там зноў будзе пустата.

І мне здаецца, што гэта робіцца для таго, каб можна было сказаць, што на гэтым этапе 702 чакае 703, а ўсе тыя, хто прыйдуць пасля гэтага, у іх не будзе ніякага запісу ў гэтым полі. Але як толькі першы які чакае пакідае, і ўсе тыя, хто чакалі ў гэты момант да абнаўлення, атрымліваюць той жа самы маркер. І таму, мне падаецца, гэта зроблена для таго, каб мы маглі апрацоўваць па парадку, каб яны былі правільна ўпарадкаваны.

Я заўсёды глядзеў на гэта, як на дастаткова дзіўны феномен. Бо тут, напрыклад, іх увогуле не пералічваем. Але, мне здаецца, кожны раз, калі мы даем новы lock, то мы глядзім на ўсіх тых, хто знаходзіцца ў працэсе чакання. Тады мы іх усіх выбудоўваем у чаргу. А затым любы новы, які прыходзіць, пападае ў чаргу толькі тады, калі наступны чалавек скончыў апрацоўвацца. Вельмі добрае пытаньне. Дзякуй вам вялікі за пытанне!

Мне здаецца, нашмат больш лагічна, калі 705 чакае 704.

Але праблема тут наступная. Тэхнічна вы можаце абудзіць ці той, ці той. І таму мы абудзім той ці іншы. Але што адбываецца ў рабоце сістэмы? Вы бачыце, як 703 у самым версе заблакаваў свой уласны транзакцыйны ID. Гэта тое, як Postgres працуе. І 703 блакуецца ўласным транзакцыйным ID, таму, калі нехта хоча пачакаць, то ён будзе чакаць 703. І, па сутнасці, 703 завяршае. І толькі пасля яго завяршэння нейкі з працэсаў абуджаецца. І мы ня ведаем, які менавіта гэты працэс будзе. Затым мы паступова ўсё апрацоўваем. Але не зразумела які менавіта працэс абуджаецца першым, таму што гэта можа быць любы з гэтых працэсаў. Па сутнасці, у нас быў планавальнік, які казаў, што мы зараз можам абуджаць любы з гэтых працэсаў. Мы проста выбіраем адзін выпадковым чынам. Таму абодва з іх трэба адзначыць, таму што мы можам абуджаць любы з іх.

І праблема ў тым, што ў нас CP-бясконцасць. І таму цалкам верагодна можам абудзіць пазнейшы. І калі, напрыклад, мы будзем абуджаць пазнейшы, то будзем чакаць таго, хто толькі што атрымаў блакіроўку, таму мы не вызначаем, хто менавіта будзе абуджаны першым. Мы ствараем проста такую ​​сітуацыю, і сістэма будзе іх абуджаць у адвольным парадку.

Ёсць артыкулы пра locks Ягора Рогава. Паглядзіце, яны таксама цікавыя і карысныя. Тэма, вядома, жудасна складаная. Дзякуй вялікі, Брус!

Крыніца: habr.com

Дадаць каментар