Отключване на Postgres Lock Manager. Брус Момджиян

Транскрипция на лекцията на Брус Момджиан от 2020 г. „Отключване на мениджъра за заключване на Postgres“.

Отключване на Postgres Lock Manager. Брус Момджиян

(Забележка: Можете да получите всички SQL заявки от слайдовете на тази връзка: http://momjian.us/main/writings/pgsql/locking.sql)

Здравейте! Страхотно е да съм отново тук в Русия. Съжалявам, че миналата година не можах да дойда, но тази година с Иван имаме големи планове. Надявам се да съм тук много по-често. Обичам да идвам в Русия. Ще посетя Тюмен, Твер. Много се радвам, че ще мога да посетя тези градове.

Казвам се Брус Момджиян. Работя в EnterpriseDB и работя с Postgres повече от 23 години. Живея във Филаделфия, САЩ. Пътувам около 90 дни в годината. И присъствам на около 40 конференции. моя уеб сайт, който съдържа слайдовете, които ще ви покажа сега. Затова след конференцията можете да ги изтеглите от личния ми сайт. Съдържа и около 30 презентации. Освен това има видеоклипове и голям брой записи в блогове, повече от 500. Това е доста информативен ресурс. И ако се интересувате от този материал, тогава ви каня да го използвате.

Преди да започна да работя с Postgres, бях учител, професор. И много се радвам, че сега мога да ви кажа това, което ще ви кажа. Това е една от най-интересните ми презентации. И тази презентация съдържа 110 слайда. Ще започнем да говорим с прости неща, а към края на доклада ще става все по-сложно и ще стане доста сложно.

Отключване на Postgres Lock Manager. Брус Момджиян

Това е доста неприятен разговор. Блокирането не е най-популярната тема. Искаме да изчезне някъде. Все едно отиваш на зъболекар.

Отключване на Postgres Lock Manager. Брус Момджиян

  1. Заключването е проблем за много хора, които работят с бази данни и имат множество процеси, работещи едновременно. Имат нужда от блокиране. Тоест днес ще ви дам основни познания за блокирането.
  2. Идентификационни номера на транзакции. Това е доста скучна част от презентацията, но те трябва да бъдат разбрани.
  3. След това ще говорим за видовете блокиране. Това е доста механична част.
  4. И тогава ще дадем няколко примера за блокиране. И ще бъде доста трудно за разбиране.

Отключване на Postgres Lock Manager. Брус Момджиян

Да поговорим за блокирането.

Отключване на Postgres Lock Manager. Брус Момджиян

Нашата терминология е доста сложна. Колко от вас знаят откъде идва този пасаж? Двама души. Това е от игра, наречена Colossal Cave Adventure. Мисля, че беше текстова компютърна игра през 80-те години. Там беше необходимо да се влезе в пещерата, в лабиринта и текстът се промени, но съдържанието беше приблизително същото всеки път. Така помня този мач.

Отключване на Postgres Lock Manager. Брус Момджиян

И тук виждаме името на ключалките, дошли при нас от Oracle. Ние ги използваме.

Отключване на Postgres Lock Manager. Брус Момджиян

Тук виждаме термини, които ме объркват. Например, SHARE UPDATE ECXLUSIVE. Следващ СПОДЕЛЕТЕ RAW EXXLUSIVE. Честно казано, тези имена не са много ясни. Ще се опитаме да ги разгледаме по-подробно. Някои съдържат думата „споделяне“, което означава разделяне. Някои съдържат думата "exclusive" - ​​изключителен. Някои съдържат и двете думи. Бих искал да започна с това как работят тези брави.

Отключване на Postgres Lock Manager. Брус Момджиян

И думата „достъп“ също е много важна. И думите "ред" - линия. Тоест разпределение на достъпа, разпределение на редове.

Отключване на Postgres Lock Manager. Брус Момджиян

Друг проблем, който трябва да бъде разбран в Postgres, който за съжаление няма да мога да покрия в моя доклад, е MVCC. Имам отделна презентация по тази тема на моя уебсайт. И ако смятате, че тази презентация е трудна, тогава MVCC е може би най-трудната за мен. А при интерес може да го видите в сайта. Можете да гледате видеото.

Отключване на Postgres Lock Manager. Брус Момджиян

Друго нещо, което трябва да разберем, са идентификаторите на транзакциите. Много транзакции не могат да работят без уникални идентификатори. И тук имаме обяснение какво е транзакция. Postgres има две системи за номериране на транзакции. Знам, че не е много красиво решение.

Отключване на Postgres Lock Manager. Брус Момджиян

Също така имайте предвид, че слайдовете ще бъдат доста трудни за четене, така че това, което е маркирано в червено, е това, на което трябва да обърнете внимание.

Отключване на Postgres Lock Manager. Брус Момджиян

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

Ние гледаме. Номерът на транзакцията е маркиран в червено. Тук е показана функцията SELECT pg_back. Връща моята транзакция и идентификационния номер на тази транзакция.

Още нещо, ако харесвате тази презентация и искате да я стартирате във вашата база данни, тогава можете да следвате тази връзка, маркирана в розово, и да изтеглите SQL за тази презентация. И можете просто да го стартирате във вашия PSQL и цялата презентация ще бъде на екрана ви за нула време. Няма да съдържа цветя, но поне можем да го видим.

Отключване на Postgres Lock Manager. Брус Момджиян

В този случай виждаме идентификатора на транзакцията. Това е номерът, който й дадохме. Има и друг тип идентификатор на транзакция в Postgres, наречен идентификатор на виртуална транзакция

И ние трябва да разберем това. Това е много важно, в противен случай няма да можем да разберем заключването в Postgres.

Виртуален идентификатор на транзакция е идентификатор на транзакция, който не съдържа постоянни стойности. Например, ако изпълня команда SELECT, тогава най-вероятно няма да променя базата данни, няма да заключвам нищо. Така че, когато изпълняваме прост SELECT, ние не даваме на транзакцията постоянен идентификатор. Там й даваме само виртуална лична карта.

И това подобрява производителността на Postgres, подобрява възможността за почистване, така че ID на виртуалната транзакция се състои от две числа. Първото число преди наклонената черта е ID на бекенда. А отдясно виждаме само брояч.

Отключване на Postgres Lock Manager. Брус Момджиян

Следователно, ако изпълня заявка, тя казва, че бекенд ID е 2.

Отключване на Postgres Lock Manager. Брус Момджиян

И ако изпълня поредица от такива транзакции, тогава виждаме, че броячът се увеличава всеки път, когато изпълня заявката. Например, когато стартирам заявка 2/10, 2/11, 2/12 и т.н.

Отключване на Postgres Lock Manager. Брус Момджиян

Имайте предвид, че тук има две колони. Вляво виждаме ID на виртуалната транзакция - 2/12. А отдясно имаме постоянен идентификатор на транзакция. И това поле е празно. И тази транзакция не променя базата данни. Следователно не му присвоявам постоянен идентификатор на транзакция.

Отключване на Postgres Lock Manager. Брус Момджиян

Веднага щом изпълня командата за анализ ((ANALYZE)), същата заявка ми дава постоянен идентификатор на транзакция. Вижте как сме се променили. Преди нямах тази лична карта, сега имам.

Отключване на Postgres Lock Manager. Брус Момджиян

Ето още една заявка, друга транзакция. Номерът на виртуалната транзакция е 2/13. И ако поискам постоянен идентификатор на транзакция, тогава, когато изпълня заявката, ще го получа.

Отключване на Postgres Lock Manager. Брус Момджиян

И така, още веднъж. Имаме идентификатор на виртуална транзакция и постоянен идентификатор на транзакция. Просто вземете тази точка, за да разберете поведението на Postgres.

Отключване на Postgres Lock Manager. Брус Момджиян

Преминаваме към трети раздел. Тук просто ще разгледаме различните видове ключалки в Postgres. Не е много интересно. Последният раздел ще бъде много по-интересен. Но трябва да се съобразяваме с основните неща, защото иначе няма да разберем какво ще последва.

Ще преминем през този раздел, ще разгледаме всеки тип блокиране. И ще ви покажа примери за това как се инсталират, как работят, ще ви покажа някои заявки, които можете да използвате, за да видите как работи блокирането в 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 във фонов режим, тогава стартирам втората сесия от първата си сесия по този начин. Тоест какво ще правя тук? Отивам на друга сесия и му казвам "покажи ми изгледа за заключване за тази заявка". И тук имам 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 в XNUMX таблици. Защо? Три таблици са маркирани в синьо: pg_attribute, pg_class, pg_namespace. Но можете също да видите, че всички индекси, които са дефинирани чрез тези таблици, също имат AccessShareLock.

И това е блокиране, което практически не противоречи на другите. И всичко, което прави, е просто да ни предпази от изпускане на таблицата, докато я избираме. Има смисъл. Тоест, ако изберем таблица, тя изчезва в този момент, тогава това е грешно, следователно AccessShare е заключване на ниско ниво, което ни казва „не изтривайте тази таблица, докато работя“. По принцип това е всичко, което тя прави.

Отключване на Postgres Lock Manager. Брус Момджиян

ROW SHARE - Тази ключалка е малко по-различна.

Отключване на Postgres Lock Manager. Брус Момджиян

Да вземем пример. SELECT ROW SHARE начин за заключване на всеки ред поотделно. По този начин никой не може да ги изтрие или промени, докато ги гледаме.

Отключване на Postgres Lock Manager. Брус МомджиянИ така, какво прави SHARE LOCK? Виждаме, че ID на транзакцията е 681 за SELECT. И е интересно. Какво е станало тук? За първи път виждаме номера в полето "Заключване". Взимаме идентификатора на транзакцията и той казва, че го блокира в изключителен режим. Всичко, което прави, е, че казва, че имам ред, който технически е заключен някъде в таблицата. Но не казва къде точно. Ще разгледаме това по-подробно малко по-късно.

Отключване на Postgres Lock Manager. Брус Момджиян

Тук казваме, че ключалката се използва от нас.

Отключване на Postgres Lock Manager. Брус Момджиян

И така, изключителна ключалка изрично (изрично) казва, че е изключителна. И също така, ако изтриете ред в тази таблица, това се случва, както можете да видите.

Отключване на Postgres Lock Manager. Брус Момджиян

SHARE EXCLUSIVE е по-дълъг кичур.

Отключване на Postgres Lock Manager. Брус Момджиян

Това е (ANALYZE) командата на анализатора, която ще се използва.

Отключване на Postgres Lock Manager. Брус Момджиян

ЗАКЛЮЧВАНЕ НА СПОДЕЛЯНЕ - Можете изрично да заключите в режим на споделяне.

Отключване на Postgres Lock Manager. Брус Момджиян

Можете също да създадете уникален индекс. И там можете да видите SHARE LOCK, който е част от тях. И той заключва масата и задава заключване SHARE LOCK върху нея.

Стандартното ЗАКЛЮЧВАНЕ НА СПОДЕЛЯНЕ на таблица означава, че други хора могат да четат таблицата, но никой не може да я променя. И точно това се случва, когато създадете уникален индекс.

Ако създам уникален паралелен индекс, тогава ще имам различен тип заключване, защото не забравяйте, че използването на едновременни индекси намалява изискването за заключване. И ако използвам нормално заключване, нормален индекс, тогава предотвратявам писането в индекса на таблицата по време на нейното създаване. Ако използвам паралелен индекс, тогава трябва да използвам различен тип заключване.

Отключване на Postgres Lock Manager. Брус Момджиян

SHARE ROW EXCLUSIVE - отново може да се зададе изрично (изрично).

Отключване на Postgres Lock Manager. Брус Момджиян

Или можем да създадем правило, тоест да вземем някакъв конкретен случай, в който ще се използва.

Отключване на Postgres Lock Manager. Брус Момджиян

ЕКСКЛУЗИВНО заключване означава, че никой друг не може да промени масата.

Отключване на Postgres Lock Manager. Брус Момджиян

Тук виждаме различни видове брави.

Отключване на Postgres Lock Manager. Брус Момджиян

ACCESS EXCLUSIVE, например, е команда за заключване. Например, ако го направите CLUSTER table, тогава това ще означава, че никой няма да може да пише там. И заключва не само самата таблица, но и индексите.

Отключване на Postgres Lock Manager. Брус Момджиян

Това е втората страница на ключалката ACCESS EXCLUSIVE, където виждаме какво точно заключва в таблицата. Той заключва отделни редове на таблицата, което е достатъчно интересно.

Това е цялата основна информация, която исках да дам. Говорихме за ключалки, за идентификатори на транзакции, говорихме за идентификатори на виртуални транзакции, за постоянни идентификатори на транзакции.

Отключване на Postgres Lock Manager. Брус Момджиян

А сега ще преминем през примерите за блокиране. Това е най-интересната част. Ще видим много интересни случаи. И моята цел в тази презентация е да ви дам по-добра представа за това какво всъщност прави Postgres, когато се опитва да блокира нещата. Струва ми се, че е много добър в блокирането на отделни части.

Нека да разгледаме някои конкретни примери.

Отключване на Postgres Lock Manager. Брус Момджиян

Ще започнем с таблици и по един ред на таблица. Когато вмъкна нещо, получавам ExclusiveLock, ID на транзакцията и ExclusiveLock на масата.

Отключване на Postgres Lock Manager. Брус Момджиян

Какво се случва, ако вмъкна още два реда? И сега нашата таблица има три реда. И аз вмъкнах един ред и получих това като изход. И ако вмъкна още два реда, какво странно има тук? Тук има странност, защото добавих три реда към тази таблица, но все още имам два реда в таблицата за заключване. И това всъщност е фундаменталното поведение на Postgres.

Много хора смятат, че ако в база данни заключите 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. Можете да видите идентификатора на транзакцията, която е направила това вмъкване. И това е как работи.

Отключване на Postgres Lock Manager. Брус Момджиян

И ако сега погледна моя бекенд 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, той е по-висок. И какво направи първата сесия? Тя създаде ексклузивно заключване на собствения си идентификатор на транзакция. Ето как го прави Postgres. Той блокира своя собствен идентификатор на транзакция. И ако искате да изчакате някой да се ангажира или отмени, тогава трябва да изчакате, докато има чакаща транзакция. И така можем да видим странна линия.

Нека погледнем отново. Отляво виждаме нашия ID за обработка. Във втората колона виждаме нашия идентификатор на виртуална транзакция, а в третата виждаме lock_type. Какво означава това? Всъщност тя казва, че блокира идентификатора на транзакцията. Но забележете, че във всички редове най-отдолу е написана връзка. И така имате два вида ключалки на масата. Има заключване на връзката. И също така има заключване на транзакция, където ви заключваме сами, точно това се случва на първия ред или в най-долния край, където е транзакция, където очакваме 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. И идентификатор на транзакция 702.

Отключване на Postgres Lock Manager. Брус Момджиян

И тогава ще разменя 4 за 5. И 5 за 6, и 6 за 7. И подреждам няколко души, които да чакат тази транзакция да завърши.

Отключване на Postgres Lock Manager. Брус Момджиян

И всичко става ясно. Какъв е първият ред? Това е 702. Това е идентификаторът на транзакцията, който първоначално е задал тази стойност. Какво имам в колоната „Разрешено“? Имам белези f. Това са моите актуализации, които (5, 6, 7) не могат да бъдат одобрени, защото чакаме изтичането на ID на транзакцията 702. Там имаме заключване на ID на транзакция. И се оказва 5 идентификатора за заключване на транзакция.

И ако погледнете 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 да бъде даден на такъв и такъв идентификатор на транзакция и да бъде блокиран от такъв и такъв процес. Следователно има ситуация на мъртво блокиране.

Отключване на 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. Брус Момджиян

И ако запазим точката и след това я актуализираме, тогава получаваме нов идентификатор на транзакция. Това е друго поведение, с което трябва да сте наясно. Ако върнем това, идентификаторът на транзакцията го няма. 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 какви идентификатори на процеси чака. И можете да видите, че 11740 очаква 724. А 724 е най-отгоре. А 11306 е идентификаторът на вашия процес. По същество тази функция надхвърля вашата заключваща таблица. И знам, че е малко сложно, но схващате идеята. По същество тази функция преминава през тази заключваща таблица и се опитва да намери къде е този ID на процеса, като се имат предвид заключванията, които чака. И също така се опитва да разбере кой идентификатор на процес има процесът, който чака за заключване. Така че можете да стартирате тази функция pg_blocking_pids.

И това е много полезно. Добавихме това едва след версия 9.6, така че тази функция е само на 5 години, но е много, много полезна. Същото важи и за второто искане. Показва точно това, което трябва да видим.

Отключване на Postgres Lock Manager. Брус Момджиян

Ето за това исках да говоря с теб. И както очаквах, използвахме цялото си време, защото имаше толкова много слайдове. И слайдовете са достъпни за изтегляне. Бих искал да ви благодаря, че сте тук. Сигурен съм, че ще се насладите на останалата част от конференцията, благодаря ви много!

въпроси:

Например, ако се опитам да актуализирам редовете и втората сесия се опита да изтрие цялата таблица. Доколкото разбирам, трябва да има нещо като intent lock. Има ли такова нещо в Postgres?

Отключване на Postgres Lock Manager. Брус Момджиян

Връщаме се в самото начало. Може би си спомняте, че когато правите нещо, например когато правите SELECT, ние издаваме AccessShareLock. И предотвратява изпускането на масата. Така че, ако например искате да актуализирате ред в таблица или да изтриете ред, тогава някой не може да изтрие цялата таблица едновременно, защото държите този AccessShareLock върху цялата таблица и над реда. И след като сте готови, те могат да го премахнат. Но докато директно промените нещо там, те няма да могат да го направят.

Нека го направим отново. Да преминем към примера за изтриване. И виждате как редът има изключително заключване върху цялата маса.

Ще изглежда като изключителна ключалка, нали?

Да, така изглежда. Разбирам за какво говориш. Искате да кажете, че ако направя SELECT, тогава имам ShareExclusive и след това го поставя в състояние Row Exclusive, това става ли проблем? Но изненадващо това не представлява проблем. Това е като увеличаване на степента на заключване, но по същество имам заключване, което предотвратява изтриването му. И сега, когато направя тази ключалка по-мощна, тя все още предотвратява изтриването. Така че не е като да се качвам. Т.е. предотврати го и когато беше на по-ниско ниво, така че когато го издигна, пак предотвратява изпускането на масата.

Разбирам за какво говориш. Няма случай на увеличаване на степента на блокиране, при който се опитвате да се откажете от един блок, за да въведете по-мощен. Тук просто увеличава това избягване навсякъде, така че не предизвиква никакъв конфликт. Но това е добър въпрос. Благодаря ви много, че попитахте!

Какво трябва да направим, за да избегнем безизходна ситуация, когато имаме много сесии, голям брой потребители?

Postgres автоматично забелязва ситуации на блокиране. И автоматично ще изтрие една от сесиите. Единственият начин да избегнете безизходна ситуация е да блокирате хората в същия ред. Така че, когато погледнете приложението си, това често е причината за блокиране... Да кажем, че искам да блокирам две различни неща. Едно приложение заключва таблица 1, а друго приложение заключва таблица 2 и след това таблица 1. И най-лесният начин да избегнете блокировки е да погледнете вашето приложение и да се опитате да се уверите, че заключването се случва в същия ред във всички приложения. И това обикновено премахва 80% от проблемите, защото всякакви хора пишат тези приложения. И ако ги блокирате в същия ред, тогава няма да попаднете в ситуация на задънена улица.

Благодаря ви много за представянето ви! Говорихте за пълен вакуум и, ако разбирам правилно, пълен вакуум изкривява реда на записите в отделно хранилище, така че запазва текущите записи непроменени. Защо vacuum full взема изключителен достъп за заключване и защо е в конфликт с операциите за запис?

Това е добър въпрос. Причината е, че вакуумът пълен заема маса. И по същество създаваме нова версия на таблицата. И масата ще е нова. Оказва се, че това ще бъде напълно нова версия на масата. И проблемът е, че когато правим това, не искаме хората да го четат, защото искаме те да видят новата таблица. И това е свързано с предишния въпрос. Ако можехме да четем едновременно, тогава нямаше да можем да го преместим и да насочим хората към нова маса. Ще трябва да изчакаме всички да приключат с четенето на тази таблица и така, по същество, това е ситуация с изключителна ключалка.
Просто казваме, че заключваме от самото начало, защото знаем, че ще се нуждаем от изключително заключване в самия край, за да преместим всички към новото копие. Така че потенциално можем да го разрешим. И ето как го правим с едновременно индексиране. Но това е много по-трудно да се направи. И това се отнася много силно за предишния ви въпрос относно ексклузивното заключване.

Възможно ли е да се добави таймаут за заключване в Postgres? В Oracle мога например да напиша „изберете за актуализиране“ и да изчакам 50 секунди, преди да актуализирам. Добре беше за приложението. Но в Postgres или трябва да направя това веднага и да не чакам изобщо, или да изчакам известно време.

Да, можете да изберете да изчакате вашите ключалки, вашите ключалки. Можете също да издадете командата no way, която ще бъде ... ако не можете да получите ключалката веднага. Следователно или изчакване за заключване, или нещо друго, което ще ви позволи да направите това. Това не се прави на синтактично ниво. Това се прави като променлива на сървъра. Понякога не може да се използва.

Можете ли да отворите слайд 75?

Да.

Отключване на Postgres Lock Manager. Брус Момджиян

И моят въпрос е следващият. Защо и двата процеса на актуализиране чакат 703?

И това е страхотен въпрос. Между другото, не разбирам защо Postgres прави това. Но когато 703 беше създаден, той чакаше 702. И когато 704 и 705 се появиха, те изглежда не знаят какво чакат, защото там все още няма нищо. А Postgres го прави така: когато не можете да получите ключалка, той казва "Какъв е смисълът да ви обработвам?", Защото вече чакате някого. Така че просто го оставете да виси във въздуха, той изобщо не го актуализира. Но какво се случи тук? Веднага след като 702 завърши процеса и 703 получи своето заключване, системата се върна обратно. И тя каза, че сега имаме двама души, които чакат. И тогава нека ги актуализираме заедно. И посочете, че се очакват и двете.

Не знам защо Postgres прави това. Но има проблем, наречен f…. Струва ми се, че това не е термин на руски. Това е, когато всеки чака един замък, дори ако има 20 инстанции, които чакат замъка. И изведнъж всички се събуждат едновременно. И всеки започва да се опитва да реагира. Но системата прави така, че всички чакат 703. Защото всички чакат и веднага ще ги наредим всички. И ако се появи друга нова заявка, която е била формирана след това, например 707, тогава отново ще има празнота.

И струва ми се, че това се прави, за да може да се каже, че на този етап 702 чака 703 и всички, които идват след това, те няма да имат никакво влизане в това поле. Но веднага щом първият сервитьор си тръгне и всички, които са чакали в този момент преди актуализацията, получават същия знак. И така ми се струва, че това се прави, за да можем да обработваме по ред, така че да са правилно подредени.

Винаги съм гледал на това като на доста странен феномен. Защото тук, например, те изобщо не са посочени. Но, струва ми се, всеки път, когато даваме нова ключалка, гледаме всички, които са в процес на чакане. След това ги редим всичките. И след това всеки нов, който идва, се поставя на опашка само когато следващият човек приключи обработката. Много добър въпрос. Благодаря ви много за вашия въпрос!

Струва ми се много по-логично, когато 705 очаква 704.

Но проблемът тук е следният. Технически можете да събудите или един, или онзи. И така събуждаме едното или другото. Но какво се случва при работата на системата? Можете да видите как 703 най-отгоре е блокирал собствения си идентификатор на транзакция. Ето как работи Postgres. И 703 е блокиран от собствения си идентификатор на транзакция, така че ако някой иска да изчака, той ще изчака 703. И всъщност 703 завършва. И едва след завършването му един от процесите се събужда. И не знаем какъв процес ще бъде. След това постепенно обработваме всичко. Но не е ясно кой процес се събужда първи, защото може да е всеки от тези процеси. По принцип имахме планировчик, който каза, че сега можем да събудим всеки от тези процеси. Просто избираме един на случаен принцип. Следователно и двете трябва да бъдат отбелязани, защото можем да събудим всяка от тях.

И проблемът е, че имаме CP-безкрайност. И следователно е много вероятно да събудим по-късния. И ако например се събудим по-късно, тогава ще изчакаме този, който току-що е получил ключалката, така че не определяме кой точно ще бъде събуден пръв. Ние създаваме точно такава ситуация и системата ще ги събуди на случаен принцип.

Има статии за ключалките на Егор Рогов. Вижте, те също са интересни и полезни. Темата, разбира се, е ужасно сложна. Благодаря много Брус!

Източник: www.habr.com

Добавяне на нов коментар