PostgreSQL Antipatterns: "үхсэн" сүргүүдтэй тулалдаж байна

PostgreSQL-ийн дотоод механизмын онцлог нь зарим тохиолдолд маш хурдан, зарим тохиолдолд "маш хурдан биш" байх боломжийг олгодог. Өнөөдөр бид DBMS хэрхэн ажилладаг ба хөгжүүлэгч түүнтэй юу хийдэг хоорондын зөрчилдөөний сонгодог жишээн дээр анхаарлаа хандуулах болно. UPDATE ба MVCC зарчим.

-аас товч түүх гайхалтай нийтлэл:

UPDATE командын тусламжтайгаар мөрийг өөрчлөхөд DELETE болон INSERT гэсэн хоёр үйлдэл хийгдэнэ. IN мөрийн одоогийн хувилбар xmax нь UPDATE хийсэн гүйлгээний тоотой тэнцүү байна. Дараа нь үүнийг бий болгодог шинэ хувилбар ижил шугам; түүний xmin утга нь өмнөх хувилбарын xmax утгатай давхцаж байна.

Энэ гүйлгээ дууссаны дараа хэсэг хугацааны дараа хуучин эсвэл шинэ хувилбараас хамаарна COMMIT/ROOLBACK, танигдах болно "үхсэн" (үхсэн залгуурууд) өнгөрөх үед VACUUM хүснэгтийн дагуу, цэвэрлэсэн.

PostgreSQL Antipatterns: "үхсэн" сүргүүдтэй тулалдаж байна

Гэхдээ энэ нь тэр даруй тохиолдохгүй, гэхдээ "үхсэн" -тэй холбоотой асуудлыг маш хурдан олж авах боломжтой - давтан эсвэл бүртгэлийг бөөнөөр нь шинэчлэх том ширээн дээр, мөн хэсэг хугацааны дараа та ижил нөхцөл байдалтай тулгарах болно VACUUM туслах боломжгүй болно.

№1: Би үүнийг хөдөлгөх дуртай

Таны арга бизнесийн логик дээр ажиллаж байна гэж бодъё, гэнэт тэр X талбарыг ямар нэгэн бичлэгт шинэчлэх шаардлагатайг ойлгов:

UPDATE tbl SET X = <newX> WHERE pk = $1;

Дараа нь гүйцэтгэл ахих тусам Y талбарыг мөн шинэчлэх шаардлагатай болж байна.

UPDATE tbl SET Y = <newY> WHERE pk = $1;

... тэгээд бас Z - яагаад жижиг зүйлд цагаа дэмий үрдэг вэ?

UPDATE tbl SET Z = <newZ> WHERE pk = $1;

Одоо мэдээллийн санд энэ бичлэгийн хэдэн хувилбар байгаа вэ? Тийм ээ, 4 ширхэг! Эдгээрийн нэг нь хамааралтай бөгөөд 3-ыг нь [авто]ВАКУМаар цэвэрлэх шаардлагатай.

Ингэж болохгүй! Ашиглах бүх талбарыг нэг хүсэлтээр шинэчлэх - бараг үргэлж аргын логикийг дараах байдлаар өөрчилж болно.

UPDATE tbl SET X = <newX>, Y = <newY>, Z = <newZ> WHERE pk = $1;

№2: IS DISTINCT FROM ашиглана уу, Лук!

Тиймээс, та хүссэн хэвээр байна Хүснэгт дэх олон, олон бичлэгийг шинэчлэх (жишээ нь скрипт эсвэл хөрвүүлэгчийг ашиглах үед). Ийм зүйл скрипт рүү орж ирдэг:

UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2;

Ойролцоогоор энэ маягтын хүсэлт нь ихэвчлэн хоосон шинэ талбарыг бөглөх биш харин өгөгдлийн зарим алдааг засахын тулд байнга тохиолддог. Үүний зэрэгцээ тэр өөрөө одоо байгаа мэдээллийн үнэн зөвийг огт авч үздэггүй - гэхдээ дэмий хоосон! Өөрөөр хэлбэл, бичлэг нь яг хүссэн зүйлээ агуулсан байсан ч дахин бичигдсэн байдаг - гэхдээ яагаад? Үүнийг засъя:

UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2 AND X IS DISTINCT FROM <newX>;

Ийм гайхалтай оператор байдгийг олон хүмүүс мэддэггүй тул энд нэг луйвар хуудас байна IS DISTINCT FROM болон бусад логик операторууд туслах болно:
PostgreSQL Antipatterns: "үхсэн" сүргүүдтэй тулалдаж байна
... мөн цогцолбор дээрх үйл ажиллагааны талаар бага зэрэг ROW()- илэрхийллүүд:
PostgreSQL Antipatterns: "үхсэн" сүргүүдтэй тулалдаж байна

#3: Би хайртыгаа... блоклосноор таньдаг

эхлүүлж байна Хоёр ижил зэрэгцээ үйл явц, тус бүр нь оруулгыг "ажиллаж байна" гэж тэмдэглэхийг оролддог:

UPDATE tbl SET processing = TRUE WHERE pk = $1;

Хэдийгээр эдгээр процессууд нь бие биенээсээ хамааралгүй үйлдлүүдийг хийдэг ч нэг ID дотор хоёр дахь үйлчлүүлэгч эхний гүйлгээ дуусах хүртэл энэ хүсэлтийг "түгжигдсэн" болно.

Шийдэл №1: даалгаврыг өмнөх болгон бууруулсан

Дахин нэмчихье IS DISTINCT FROM:

UPDATE tbl SET processing = TRUE WHERE pk = $1 AND processing IS DISTINCT FROM TRUE;

Энэ маягт дээр хоёр дахь хүсэлт нь мэдээллийн санд юу ч өөрчлөгдөхгүй, бүх зүйл байх ёстой шигээ байгаа тул блоклохгүй. Дараа нь бид ашигласан алгоритм дахь бичлэгийг "олоогүй" гэсэн баримтыг боловсруулдаг.

Шийдэл №2: зөвлөх түгжээ

Тусдаа нийтлэлийн том сэдэв бөгөөд та үүнийг уншиж болно хэрэглэх арга, зөвлөмжийн блоклох "тармуур".

Шийдэл №3: тэнэг дуудлага

Гэхдээ энэ нь танд тохиолдох ёстой зүйл юм ижил бичлэгтэй нэгэн зэрэг ажиллах? Эсвэл та жишээ нь үйлчлүүлэгчийн тал дээр бизнесийн логикийг дуудах алгоритмуудыг будилуулсан уу? Тэгээд бодох юм бол?..

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх