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

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

Товч үйл явдал гайхалтай нийтлэл:

UPDATE командын тусламжтайгаар мөрийг өөрчлөхөд УСТГАХ, INSERT гэсэн хоёр үйлдэл хийгдэнэ. шугамын одоогийн хувилбар 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;

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

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

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