PostgreSQL Antipatterns: Π±ΠΎΡ€Π±Π° с ΠΎΡ€Π΄ΠΈΡ‚Π΅ Π½Π° β€žΠΌΡŠΡ€Ρ‚Π²ΠΈΡ‚Π΅β€œ

ΠžΡΠΎΠ±Π΅Π½ΠΎΡΡ‚ΠΈΡ‚Π΅ Π½Π° Π²ΡŠΡ‚Ρ€Π΅ΡˆΠ½ΠΈΡ‚Π΅ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠΈ Π½Π° PostgreSQL ΠΌΡƒ позволяват Π΄Π° бъдС ΠΌΠ½ΠΎΠ³ΠΎ Π±ΡŠΡ€Π· Π² някои ситуации ΠΈ β€žΠ½Π΅ ΠΌΠ½ΠΎΠ³ΠΎ Π±ΡŠΡ€Π·β€œ Π² Π΄Ρ€ΡƒΠ³ΠΈ. ДнСс Ρ‰Π΅ сС ΡΡŠΡΡ€Π΅Π΄ΠΎΡ‚ΠΎΡ‡ΠΈΠΌ Π²ΡŠΡ€Ρ…Ρƒ класичСски ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° ΠΊΠΎΠ½Ρ„Π»ΠΈΠΊΡ‚ ΠΌΠ΅ΠΆΠ΄Ρƒ Ρ‚ΠΎΠ²Π° ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚ΠΈ Π‘Π£Π‘Π” ΠΈ ΠΊΠ°ΠΊΠ²ΠΎ ΠΏΡ€Π°Π²ΠΈ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΡŠΡ‚ с нСя - UPDATE срСщу MVCC ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠΈ.

ΠšΡ€Π°Ρ‚ΠΊΠ° история ΠΎΡ‚ страхотна статия:

ΠšΠΎΠ³Π°Ρ‚ΠΎ Ρ€Π΅Π΄ сС ΠΌΠΎΠ΄ΠΈΡ„ΠΈΡ†ΠΈΡ€Π° Ρ‡Ρ€Π΅Π· ΠΊΠΎΠΌΠ°Π½Π΄Π° UPDATE, Π²ΡΡŠΡ‰Π½ΠΎΡΡ‚ сС ΠΈΠ·ΠΏΡŠΠ»Π½ΡΠ²Π°Ρ‚ Π΄Π²Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ: DELETE ΠΈ INSERT. IN Ρ‚Π΅ΠΊΡƒΡ‰Π°Ρ‚Π° вСрсия Π½Π° Π½ΠΈΠ·Π° xmax Π΅ Π·Π°Π΄Π°Π΄Π΅Π½ Ρ€Π°Π²Π΅Π½ Π½Π° Π½ΠΎΠΌΠ΅Ρ€Π° Π½Π° транзакцията, която Π΅ ΠΈΠ·Π²ΡŠΡ€ΡˆΠΈΠ»Π° ΠΠšΠ’Π£ΠΠ›Π˜Π—ΠΠ¦Π˜Π―Π’Π. Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π° сС създава Π½ΠΎΠ²Π° вСрсия ΡΡŠΡ‰Π°Ρ‚Π° линия; Π½Π΅Π³ΠΎΠ²Π°Ρ‚Π° 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 Ρ‰Π΅ трябва Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ почистСни слСд вас Ρ‡Ρ€Π΅Π· [auto]VACUUM.

НС Π³ΠΎ ΠΏΡ€Π°Π²Π΅Ρ‚Π΅ ΠΏΠΎ Ρ‚ΠΎΠ·ΠΈ Π½Π°Ρ‡ΠΈΠ½! Π˜Π·ΠΏΠΎΠ»Π·Π²Π°ΠΉΡ‚Π΅ Π°ΠΊΡ‚ΡƒΠ°Π»ΠΈΠ·ΠΈΡ€Π°Π½Π΅ Π½Π° всички ΠΏΠΎΠ»Π΅Ρ‚Π° Π² Π΅Π΄Π½Π° заявка β€” ΠΏΠΎΡ‡Ρ‚ΠΈ Π²ΠΈΠ½Π°Π³ΠΈ Π»ΠΎΠ³ΠΈΠΊΠ°Ρ‚Π° Π½Π° ΠΌΠ΅Ρ‚ΠΎΠ΄Π° ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈ ΠΏΠΎ слСдния Π½Π°Ρ‡ΠΈΠ½:

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

#2: Π˜Π·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅Ρ‚ΠΎ Π• Π ΠΠ—Π›Π˜Π§ΠΠž ОВ Π›ΡŽΠΊ!

Π—Π½Π°Ρ‡ΠΈ всС ΠΏΠ°ΠΊ искашС Π°ΠΊΡ‚ΡƒΠ°Π»ΠΈΠ·ΠΈΡ€Π°ΠΉΡ‚Π΅ ΠΌΠ½ΠΎΠ³ΠΎ, ΠΌΠ½ΠΎΠ³ΠΎ записи Π² Ρ‚Π°Π±Π»ΠΈΡ†Π° (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΏΠΎ Π²Ρ€Π΅ΠΌΠ΅ Π½Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° скрипт ΠΈΠ»ΠΈ ΠΊΠΎΠ½Π²Π΅Ρ€Ρ‚ΠΎΡ€). И Π½Π΅Ρ‰ΠΎ ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΎ Π»Π΅Ρ‚ΠΈ Π² скрипта:

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;

Π”ΠΎΡ€ΠΈ Π°ΠΊΠΎ Ρ‚Π΅Π·ΠΈ процСси дСйствитСлно ΠΈΠ·Π²ΡŠΡ€ΡˆΠ²Π°Ρ‚ Π½Π΅Ρ‰Π°, нСзависими Π΅Π΄ΠΈΠ½ ΠΎΡ‚ Π΄Ρ€ΡƒΠ³, Π½ΠΎ Π² Ρ€Π°ΠΌΠΊΠΈΡ‚Π΅ Π½Π° Π΅Π΄ΠΈΠ½ ΠΈ ΡΡŠΡ‰ΠΈ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€, вторият ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Ρ‰Π΅ бъдС β€žΠ·Π°ΠΊΠ»ΡŽΡ‡Π΅Π½β€œ ΠΏΡ€ΠΈ Ρ‚Π°Π·ΠΈ заявка, Π΄ΠΎΠΊΠ°Ρ‚ΠΎ ΠΏΡŠΡ€Π²Π°Ρ‚Π° транзакция Π½Π΅ бъдС Π·Π°Π²ΡŠΡ€ΡˆΠ΅Π½Π°.

РСшСниС #1: Π·Π°Π΄Π°Ρ‡Π°Ρ‚Π° сС свСТда Π΄ΠΎ ΠΏΡ€Π΅Π΄ΠΈΡˆΠ½Π°Ρ‚Π°

НСка просто Π³ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΠΌ ΠΎΡ‚Π½ΠΎΠ²ΠΎ IS DISTINCT FROM:

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

Π’ Ρ‚Π°Π·ΠΈ Ρ„ΠΎΡ€ΠΌΠ° Π²Ρ‚ΠΎΡ€Π°Ρ‚Π° заявка просто няма Π΄Π° ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈ Π½ΠΈΡ‰ΠΎ Π² Π±Π°Π·Π°Ρ‚Π° Π΄Π°Π½Π½ΠΈ, всичко Π²Π΅Ρ‡Π΅ Π΅ ΠΊΠ°ΠΊΡ‚ΠΎ трябва - слСдоватСлно няма Π΄Π° Π½Π°ΡΡ‚ΡŠΠΏΠΈ Π±Π»ΠΎΠΊΠΈΡ€Π°Π½Π΅. Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π²Π°ΠΌΠ΅ Ρ„Π°ΠΊΡ‚Π° β€žΠ½Π΅Π½Π°ΠΌΠΈΡ€Π°Π½Π΅β€œ Π½Π° записа Π² прилоТСния Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΡŠΠΌ.

РСшСниС #2: ΡΡŠΠ²Π΅Ρ‚Π½ΠΈ ΠΊΠ»ΡŽΡ‡Π°Π»ΠΊΠΈ

Голяма Ρ‚Π΅ΠΌΠ° Π·Π° ΠΎΡ‚Π΄Π΅Π»Π½Π° статия, Π² която ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΏΡ€ΠΎΡ‡Π΅Ρ‚Π΅Ρ‚Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΈ Π½Π° ΠΏΡ€ΠΈΠ»Π°Π³Π°Π½Π΅ ΠΈ β€žΡ€Π΅ΠΉΠΊβ€œ Π½Π° ΠΏΡ€Π΅ΠΏΠΎΡ€ΡŠΡ‡ΠΈΡ‚Π΅Π»Π½ΠΎ Π±Π»ΠΎΠΊΠΈΡ€Π°Π½Π΅.

РСшСниС #3: Π³Π»ΡƒΠΏΠ°Π²ΠΈ обаТдания

Но Ρ‚ΠΎΡ‡Π½ΠΎ Ρ‚ΠΎΠ²Π° трябва Π΄Π° Π²ΠΈ сС случи Π΅Π΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½Π° Ρ€Π°Π±ΠΎΡ‚Π° с Π΅Π΄ΠΈΠ½ ΠΈ ΡΡŠΡ‰ΠΈ запис? Или си ΠΎΠ±ΡŠΡ€ΠΊΠ°Π» Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΠΈΡ‚Π΅ Π·Π° ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅ Π½Π° бизнСс Π»ΠΎΠ³ΠΈΠΊΠ°Ρ‚Π° ΠΎΡ‚ страна Π½Π° ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€? И Π°ΠΊΠΎ сС замислитС?..

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ: www.habr.com

ДобавянС Π½Π° Π½ΠΎΠ² ΠΊΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€