Mundarija (25)
- Bu darsda
- 1. Nega bu kerak?
- 2. Vositalar xaritasi
- 3. node-pg-migrate
- 3.1 SQL fayllar
- 3.2 Bitta tranzaksiya: hammasi yoki hech narsa
- 3.3 down
- 4. CONCURRENTLY: tranzaksiyasiz migratsiya
- 4.1 Kanon: SQL faylda ishlamadi
- 4.2 JS migratsiya va noTransaction
- 5. Boshqa vositalar (sinalmagan)
- 5.1 dbmate
- 5.2 graphile-migrate
- 5.3 Atlas: deklarativ
- 5.4 Flyway va Liquibase
- 6. Tanlov
- 7. Ko'p uchraydigan xatolar
- 8. Mashqlar
- 1-mashq (oson)
- 2-mashq (o'rta)
- 3-mashq (qiyin)
- 9. Loyiha qadami
- 10. Real ishda
- Xulosa
- Manbalar
ORM'siz migratsiya: node-pg-migrate, dbmate, graphile-migrate va Atlas
Qisqacha: ORM ishlatmaydigan (yoki Kysely,
pgbilan ishlaydigan) jamoa migratsiyani alohida vosita bilan boshqaradi. node-pg-migrate — Node.js uchun eng mashhuri: SQL yoki JS fayllar,up/down,pgmigrationsholat jadvali. Kanon o'lchovi: sukut bo'yicha hamma kutilayotgan migratsiyalar bitta tranzaksiyada — uchinchisi yiqilsa, birinchi ikkitasi ham bekor (Prisma'dan farqli).CREATE INDEX CONCURRENTLYuchun JS migratsiyadapgm.noTransaction()kerak — biz sinadik, ishladi. Boshqa vositalar: dbmate (bitta binar, istalgan til), graphile-migrate (current.sqlbilan tez iteratsiya), Atlas (deklarativ — kerakli holatni yozasiz, farqni vosita hisoblaydi), Flyway/Liquibase (Java dunyosi).
Bu darsda
- ORM'siz migratsiya vositasi qachon kerakligini tushuntira olasiz.
- node-pg-migrate bilan SQL va JS migratsiyalar yozib,
upvadownqilasiz. - "Bitta tranzaksiya" va "har migratsiya alohida" rejimlarini farqlaysiz.
CONCURRENTLYuchun tranzaksiyasiz migratsiyani to'g'ri belgilaysiz.- Imperativ va deklarativ (Atlas) yondashuvlarni solishtirasiz.
Oldin bilishingiz kerak: Migratsiya tushunchasi, Xavfli migratsiyalar va qulflar, Kysely va Knex query builder'lari, Migratsiyani deploy jarayonida qo'llash.
1. Nega bu kerak?
26-qismda vazifalar-api pg bilan yozilgan edi — ORM'siz, toza SQL. Kanon sql/ papkasi esa qur.sh bilan noldan qo'llanadi. Holat 36 da biz holat jadvalini Prisma orqali oldik. Lekin Prisma'ni faqat migratsiya uchun o'rnatish qimmat: prod o'rnatish hajmi 15 MB dan 330 MB ga o'sadi (kanon o'lchovi, Prisma prodakshnda), ustiga sxema tilining cheklovlari (Prisma Migrate chuqur).
Bunday jamoalar ko'p: Kysely bilan yozadi, pg bilan yozadi, yoki API Go'da, Python'da — baza esa bitta. Ularga faqat migratsiya kerak: fayllar, tartib, holat jadvali, bir marta qo'llash. Shuning uchun alohida, kichik vositalar bor.
O'xshatish: avtomobil va velosiped. Prisma — avtomobil: ko'p narsa qiladi (client, turlar, migratsiya), lekin og'ir. node-pg-migrate yoki dbmate — velosiped: faqat bitta ish, lekin yengil va har joyda yuradi. Shahar ichida qisqa masofaga ko'pincha velosiped tezroq.
2. Vositalar xaritasi
| Vosita | Til / tarqatish | Fayllar | Yondashuv |
|---|---|---|---|
| node-pg-migrate | npm paketi | SQL yoki JS/TS | Imperativ, up/down |
| dbmate | Bitta binar (Go) | SQL (-- migrate:up/down) |
Imperativ, up/down |
| graphile-migrate | npm paketi | SQL, current.sql |
Imperativ, forward-only |
| Atlas | Binar (Go) | HCL yoki SQL sxema | Deklarativ + versiyali |
| Flyway / Liquibase | Java (CLI ham bor) | SQL / XML, YAML | Imperativ |
Kysely Migrator, umzug |
npm, kod ichida | JS/TS | Imperativ |
Kanon faqat node-pg-migrate 9.0.0 ni sinagan. Qolganlari — sinalmagan, ma'lumotlar rasmiy hujjatlardan (2026-10 holatida). umzug — sequelize-cli ichidagi migratsiya dvigateli; uni Sequelize darsida bilvosita ishlatgan edik.
3. node-pg-migrate
3.1 SQL fayllar
node-pg-migrate fayl nomi — <vaqt belgisi>_<nom>, ichida ikki bo'lim izoh bilan ajratiladi. Kanon tajribasi (fayllar o'zgarishsiz, uzun qator bo'lindi):
-- Up Migration
CREATE TABLE vazifalar (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
matn text NOT NULL CHECK (char_length(matn) BETWEEN 1 AND 100)
);
-- Down Migration
DROP TABLE vazifalar;Ikkinchi fayl 1761370000001_bajarildi.sql — ADD COLUMN bajarildi boolean NOT NULL DEFAULT false va teskarisi DROP COLUMN. Qo'llash:
npm i -D node-pg-migrate@9.0.0
npx node-pg-migrate up -m pgm-migrations-m — migratsiyalar papkasi; ulanish — DATABASE_URL muhit o'zgaruvchisidan. Kanon chiqishining boshi. Ikki qatorga qarang — ### MIGRATION … sarlavhasi va INSERT INTO "public"."pgmigrations":
### MIGRATION 1761370000000_jadvallar (UP) ###
-- Up Migration
CREATE TABLE vazifalar (id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY, matn text NOT NULL CHECK (char_length(matn) BETWEEN 1 AND 100));
;
INSERT INTO "public"."pgmigrations" (name, run_on) VALUES ('1761370000000_jadvallar', NOW());
### MIGRATION 1761370000001_bajarildi (UP) ###Har migratsiyadan keyin vosita pgmigrations jadvaliga yozadi — holat jadvali. Biz o'z bazamizda shu jadvalga qaradik (biz ishga tushirdik, node-pg-migrate 9.0.0, PostgreSQL 17.6):
Column | Type | Collation | Nullable | Default
--------+-----------------------------+-----------+----------+------------------------------------------
id | integer | | not null | nextval('pgmigrations_id_seq'::regclass)
name | character varying(255) | | not null |
run_on | timestamp without time zone | | not null | Prisma'ning _prisma_migrations iga qaraganda ancha sodda: na checksum, na "tugallanmagan" belgisi. Sabab keyingi bo'limda — sukut bo'yicha node-pg-migrate'da "yarim qolgan migratsiya" bo'lmaydi.
3.2 Bitta tranzaksiya: hammasi yoki hech narsa
Kanon uchinchi migratsiyani ataylab yiqitdi (1761370000002_yarim.sql: ADD COLUMN birinchi_qadam int; SELECT 1/0;):
### MIGRATION 1761370000002_yarim (UP) ###
-- Up Migration
[exit 1]
Did not find any relation named "vazifalar".
name
------
(0 rows)vazifalar jadvali yo'q, pgmigrations — bo'sh. Uchinchisi yiqildi va birinchi ikkitasi ham bekor bo'ldi. Sabab: node-pg-migrate sukut bo'yicha bitta up dagi hamma kutilayotgan migratsiyalarni bitta tranzaksiyaga o'raydi. Toza SQL'da bu shunday ko'rinadi (biz ishga tushirdik, PostgreSQL 17.6):
BEGIN;
-- 1761370000000_jadvallar
CREATE TABLE vazifalar (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
matn text NOT NULL CHECK (char_length(matn) BETWEEN 1 AND 100)
);
-- 1761370000001_bajarildi
ALTER TABLE vazifalar
ADD COLUMN bajarildi boolean NOT NULL DEFAULT false;
-- 1761370000002_yarim
ALTER TABLE vazifalar ADD COLUMN birinchi_qadam int;
SELECT 1/0;
COMMIT;
SELECT to_regclass('vazifalar') AS jadval;Natija:
BEGIN
CREATE TABLE
ALTER TABLE
ALTER TABLE
ERROR: division by zero
ROLLBACK
jadval
--------
(1 row)to_regclass — nomdan jadvalni topadi, yo'q bo'lsa NULL (bo'sh katak). Kanon natijasi bilan bir xil: hech narsa qolmadi.
Uch vositani yonma-yon qo'ysak (hammasi — o'lchangan):
| Vosita | 3-migratsiya yiqilsa | Holat jadvali |
|---|---|---|
| node-pg-migrate 9 (sukut) | 1, 2, 3 — hammasi bekor | Bo'sh |
Prisma 7 migrate deploy |
1, 2 qoladi; 3 ning birinchi qadami ham qoladi | 3 — "yiqilgan" (P3009) |
| sequelize-cli 6 | 1, 2 qoladi; 3 ning birinchi qadami qoladi | 3 yo'q, qayta urinish already exists |
Eng toza natija — node-pg-migrate'niki. Lekin uning ham narxi bor: 20 ta migratsiya bitta tranzaksiyada — uzun qulf; va ba'zi buyruqlar tranzaksiyada umuman ishlamaydi.
3.3 down
down — oxirgi qo'llangan migratsiyaning -- Down Migration qismini bajaradi va pgmigrations dan o'chiradi. down 2 — oxirgi ikkitasini. Kanon tajribasida yiqilgan up dan keyin down "No migrations to run!" dedi — chunki hech narsa qo'llanmagan edi. Biz qayta up (uchta migratsiya) va down qildik — natijasi keyingi bo'limda, CONCURRENTLY indeks bilan.
Tekshirib ko'ring: "Hammasi bitta tranzaksiyada" — yaxshimi yoki yomonmi? Bir afzallik va bir kamchilik ayting.
Javob
Afzallik: yarim holat bo'lmaydi — yo hammasi qo'llandi, yo hech biri; tozalash shart emas. Kamchilik: hamma migratsiyalarning qulflari oxirigacha ushlanadi — 5 ta migratsiyaning birinchisi olgan ACCESS EXCLUSIVE beshinchisi tugaguncha turadi (Xavfli migratsiyalar). Va CONCURRENTLY kabi buyruqlar umuman ishlamaydi.
4. CONCURRENTLY: tranzaksiyasiz migratsiya
4.1 Kanon: SQL faylda ishlamadi
Kanon to'rtinchi migratsiyani qo'shdi — CREATE INDEX CONCURRENTLY vazifalar_matn_idx ON vazifalar (matn);:
error: CREATE INDEX CONCURRENTLY cannot run inside a transaction block--no-single-transaction bayrog'i bilan ham:
### MIGRATION 1761370000003_indeks (UP) ###
BEGIN;
-- Up Migration
CREATE INDEX CONCURRENTLY vazifalar_matn_idx ON vazifalar (matn);
;
INSERT INTO "public"."pgmigrations" (name, run_on) VALUES ('1761370000003_indeks', NOW());
COMMIT;
Error executing:Logga qarang: --no-single-transaction "hammasi bitta tranzaksiyada" ni o'chirdi, lekin har migratsiya baribir o'z BEGIN … COMMIT ida. Ya'ni bu bayroq ikkinchi rejimga o'tkazadi — "har biri alohida tranzaksiyada" — lekin tranzaksiyasiz emas.
4.2 JS migratsiya va noTransaction
node-pg-migrate hujjatiga ko'ra yechim — JS (yoki TS) migratsiya va pgm.noTransaction(). Kanon buni sinamagan edi; biz sinadik. Fayl 1761370000002_indeks.js:
/** CONCURRENTLY tranzaksiya ichida ishlamaydi */
export const up = (pgm) => {
pgm.noTransaction();
pgm.createIndex('vazifalar', 'matn', { concurrently: true });
};
export const down = (pgm) => {
pgm.noTransaction();
pgm.dropIndex('vazifalar', 'matn', { concurrently: true });
};pgm — migratsiya quruvchisi: createTable, addColumn, createIndex, sql('…') kabi metodlar SQL yasaydi. Uchta migratsiya bilan up (biz ishga tushirdik, node-pg-migrate 9.0.0, PostgreSQL 17.6) — oxirgisi:
### MIGRATION 1761370000002_indeks (UP) ###
#> WARNING: Need to break single transaction! <
COMMIT;
CREATE INDEX CONCURRENTLY "vazifalar_matn_index" ON "vazifalar" ("matn");
INSERT INTO "public"."pgmigrations" (name, run_on) VALUES ('1761370000002_indeks', NOW());
BEGIN;
Migrations complete!Ishladi. Vosita ogohlantirdi: "bitta tranzaksiyani buzishga to'g'ri keldi" — oldingi ikki migratsiyani COMMIT qildi, indeksni tranzaksiyasiz qurdi, keyin yangi BEGIN ochdi. Bazada: vazifalar_pkey va vazifalar_matn_index, pgmigrations da uch qator. Indeks nomini vosita o'zi yasadi: <jadval>_<ustun>_index.
down:
### MIGRATION 1761370000002_indeks (DOWN) ###
#> WARNING: Need to break single transaction! <
COMMIT;
DROP INDEX CONCURRENTLY "vazifalar_matn_index";
DELETE FROM "public"."pgmigrations" WHERE name='1761370000002_indeks';
BEGIN;
Migrations complete!Indeks CONCURRENTLY bilan o'chdi, yozuv pgmigrations dan o'chirildi; qolgan ikki migratsiya joyida.
Diqqat: Tranzaksiyasiz migratsiyada atomiklik yo'q. Logga e'tibor bering:
CREATE INDEXvaINSERT INTO pgmigrations— ikki alohida buyruq. Indeks qurilgan-u, yozuv yozilmagan bo'lsa (ulanish uzildi) — keyingiupindeksni qayta qurmoqchi bo'ladi vaalready existsbilan yiqiladi. Shuning uchun tranzaksiyasiz migratsiyada bitta buyruq vaIF NOT EXISTS(Xavfli migratsiyalar —INVALIDindeks tuzog'i bilan birga).
5. Boshqa vositalar (sinalmagan)
5.1 dbmate
Go'da yozilgan bitta binar — npm, Node, ORM kerak emas. Fayl: db/migrations/20261025120000_toliq_ism.sql, ichida -- migrate:up va -- migrate:down bo'limlari. Buyruqlar: dbmate new, up, down, status, dump (sxemani schema.sql ga yozadi — review uchun qulay). Har migratsiya tranzaksiyada; -- migrate:up transaction:false — tranzaksiyasiz (dbmate README, 2026-10). Afzalligi — til tanlamaydi: Go, Python, Node servislari bitta bazani bitta vosita bilan boshqaradi.
5.2 graphile-migrate
"Faqat oldinga" (forward-only) va tez iteratsiya: siz migrations/current.sql faylini tahrirlaysiz, graphile-migrate watch uni har saqlashda lokal bazaga qayta qo'llaydi. Tayyor bo'lgach commit — fayl raqamli migratsiyaga aylanadi va hash'i bilan muzlaydi: keyin uni tahrirlasangiz, hash mos kelmaydi va vosita xato beradi. current.sql qayta-qayta qo'llanishi uchun idempotent yoziladi (DROP … IF EXISTS / CREATE OR REPLACE). PostGraphile jamoasining vositasi (hujjat, 2026-10).
5.3 Atlas: deklarativ
Hozirgacha ko'rgan hamma vosita — imperativ: siz "nima qilish kerak" ni yozasiz (ALTER TABLE … ADD COLUMN). Atlas deklarativ rejimni ham beradi: siz "qanday bo'lishi kerak" ni yozasiz (sxemaning to'liq tavsifi), Atlas joriy baza bilan farqni hisoblab, SQL rejasini o'zi tuzadi — Terraform'ning bazalar uchun varianti.
flowchart LR
subgraph Imperativ
A1[001.sql 002.sql 003.sql] --> B1[(Baza)]
end
subgraph Deklarativ
A2[schema.hcl: kerakli holat] --> C2[Atlas: farq + reja]
D2[(Joriy baza)] --> C2
C2 --> B2[ALTER rejasi, review]
endDiagrammaning o'ng tomoni Prisma'ning migrate dev iga o'xshaydi (schema.prisma → farq → SQL). Farqi: Atlas sxema tili Postgres'ning ko'p imkoniyatini (CHECK, trigger, funksiya, policy) ifodalaydi va xavfli o'zgarishlarni (DROP, qulf oladigan ALTER) avtomatik tahlil qilib ogohlantiradi — atlas migrate lint (Atlas hujjati, 2026-10). Versiyali rejim ham bor: reja fayllarga yoziladi va odatdagidek qo'llanadi. Biz Atlas'ni sinamadik.
5.4 Flyway va Liquibase
Java dunyosining eng keng tarqalgan vositalari: Flyway — V1__init.sql, V2__toliq_ism.sql kabi nomlangan SQL fayllar va flyway_schema_history jadvali; Liquibase — XML/YAML/SQL "changeset"lar. Katta korporativ loyihalarda, ayniqsa backend Java/Kotlin bo'lsa, uchratasiz. Node loyihasi uchun tanlash odatda ortiqcha — lekin qo'shni Java jamoasi bilan bitta bazani bo'lishsangiz, ular nimani ishlatayotganini bilishingiz kerak.
6. Tanlov
| Vaziyat | Tavsiya |
|---|---|
| Prisma yoki Drizzle ishlatiladi | O'zining migratsiya vositasi (migrate deploy, drizzle-kit migrate) |
Node + pg/Kysely, SQL-first |
node-pg-migrate (yoki Kysely Migrator) |
| Bir nechta tildagi servislar, bitta baza | dbmate |
| Tez lokal iteratsiya, forward-only | graphile-migrate |
| Katta sxema, avtomatik xavf tahlili kerak | Atlas (versiyali + lint) |
| Java jamoasi bilan umumiy baza | Flyway/Liquibase — o'sha jamoa tanlovi |
Qaysi vosita bo'lmasin, oldingi darslarning qoidalari o'zgarmaydi: qo'llangan fayl tahrirlanmaydi, migratsiya — alohida deploy qadami, katta jadvalda — CONCURRENTLY, NOT VALID, lock_timeout, expand-contract.
7. Ko'p uchraydigan xatolar
1. CREATE INDEX CONCURRENTLY cannot run inside a transaction block. Sukut tranzaksiyasi. Tuzatish: node-pg-migrate — JS migratsiyada pgm.noTransaction(); dbmate — transaction:false; TypeORM — transaction = false.
2. --no-single-transaction kutilgandek ishlamadi. U faqat "hammasi bitta" ni "har biri alohida" ga almashtiradi — tranzaksiyasiz qilmaydi (kanon logi).
3. Tartib xatosi. node-pg-migrate sukut bo'yicha bazadagi oxirgi migratsiyadan oldingi vaqt belgili yangi faylni rad etadi; kanon --no-check-order bilan o'tkazdi. Bu bayroqni doimiy qo'ymang — u branch'lar birlashuvidagi tartib muammosini yashiradi (Migratsiya tushunchasi, 2-mashq).
4. Holat jadvali nomi to'qnashuvi. Ikki vosita (masalan eski Knex va yangi node-pg-migrate) bitta bazada — ikki holat jadvali, ikki haqiqat. Tuzatish: bitta vosita; ko'chishda baseline.
5. Tranzaksiyasiz migratsiyada bir nechta buyruq. Yarim holat. Tuzatish: bitta buyruq, IF NOT EXISTS.
8. Mashqlar
Yechimlar tekshirilgan (biz ishga tushirdik, PostgreSQL 17.6, Node 24.21.0).
1-mashq (oson)
Har vosita qaysi yondashuvga kiradi — imperativ yoki deklarativ? (a) node-pg-migrate; (b) Atlas schema apply; (c) Prisma migrate dev; (d) dbmate; (e) TypeORM synchronize.
Yechim
(a) Imperativ — siz ALTER larni yozasiz. (b) Deklarativ — kerakli holat, reja vositada. (c) Deklarativdan imperativ fayl yasaydi: schema.prisma — kerakli holat, natija — SQL migratsiya fayli, keyin u imperativ qo'llanadi (Atlas versiyali rejimiga o'xshash). (d) Imperativ. (e) Deklarativ, lekin fayl va review'siz, to'g'ridan-to'g'ri bazaga — shuning uchun xavfli (TypeORM darsidagi DROP COLUMN).
2-mashq (o'rta)
node-pg-migrate SQL fayli formatini o'qiydigan funksiya yozing: bolimlarniAjrat(matn) → { up, down } (har biri — bo'lim ichidagi SQL, chetlaridagi bo'shliqlarsiz). -- Down Migration bo'lmasa — down: null. Ishora: indexOf, slice, trim (Kesish, bo'lish va to'ldirish).
Yechim
function bolimlarniAjrat(matn) {
const UP = "-- Up Migration";
const DOWN = "-- Down Migration";
const u = matn.indexOf(UP);
if (u === -1) throw new Error("Up bo'limi yo'q");
const d = matn.indexOf(DOWN);
const upOxiri = d === -1 ? matn.length : d;
return {
up: matn.slice(u + UP.length, upOxiri).trim(),
down: d === -1 ? null : matn.slice(d + DOWN.length).trim(),
};
}
const fayl = `-- Up Migration
ALTER TABLE vazifalar ADD COLUMN muddat timestamptz;
-- Down Migration
ALTER TABLE vazifalar DROP COLUMN muddat;
`;
console.log(bolimlarniAjrat(fayl));
console.log(bolimlarniAjrat("-- Up Migration\nSELECT 1;").down);Konsolda:
{
up: 'ALTER TABLE vazifalar ADD COLUMN muddat timestamptz;',
down: 'ALTER TABLE vazifalar DROP COLUMN muddat;'
}
nullHaqiqiy vosita yana ko'p narsani hisobga oladi (izoh ichidagi -- Up matni, $$ bloklar) — lekin asosiy g'oya shu: fayl — oddiy matn, bo'limlar — belgilangan izohlar.
3-mashq (qiyin)
«Bitta tranzaksiya» bo'limidagi uch migratsiyani har biri alohida tranzaksiyada (--no-single-transaction rejimi) qo'llang: har migratsiya o'z BEGIN … COMMIT ida va o'zini pgmigrations ga yozadi. Uchinchisi yiqilsin. Natijada qaysi migratsiyalar qolganini va holat jadvalini ko'rsating. Oxirida jadvallarni o'chiring.
Yechim
CREATE TABLE pgmigrations (id serial PRIMARY KEY,
name varchar(255) NOT NULL, run_on timestamp NOT NULL);
BEGIN;
CREATE TABLE vazifalar2 (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
matn text NOT NULL);
INSERT INTO pgmigrations (name, run_on)
VALUES ('1761370000000_jadvallar', now());
COMMIT;
BEGIN;
ALTER TABLE vazifalar2
ADD COLUMN bajarildi boolean NOT NULL DEFAULT false;
INSERT INTO pgmigrations (name, run_on)
VALUES ('1761370000001_bajarildi', now());
COMMIT;
BEGIN;
ALTER TABLE vazifalar2 ADD COLUMN birinchi_qadam int;
SELECT 1/0;
INSERT INTO pgmigrations (name, run_on)
VALUES ('1761370000002_yarim', now());
COMMIT;
SELECT name FROM pgmigrations ORDER BY id;
SELECT column_name FROM information_schema.columns
WHERE table_name = 'vazifalar2' ORDER BY ordinal_position;
DROP TABLE vazifalar2, pgmigrations;Natija:
CREATE TABLE
BEGIN
CREATE TABLE
INSERT 0 1
COMMIT
BEGIN
ALTER TABLE
INSERT 0 1
COMMIT
BEGIN
ALTER TABLE
ERROR: division by zero
ERROR: current transaction is aborted, commands ignored until end of transaction block
ROLLBACK
name
-------------------------
1761370000000_jadvallar
1761370000001_bajarildi
(2 rows)
column_name
-------------
id
matn
bajarildi
(3 rows)
DROP TABLEBirinchi ikkitasi qoldi va qayd etildi, uchinchisi to'liq bekor (birinchi_qadam yo'q) — har migratsiya alohida tranzaksiyada atomik. Bu Prisma va sequelize-cli'dan yaxshiroq (ularda uchinchining birinchi qadami qolardi), lekin "hammasi yoki hech narsa" emas: baza endi 1761370000001 holatida, xatoni tuzatib qayta up qilasiz.
9. Loyiha qadami
Bu dars vazifalar-api ga o'zgarish kiritmaydi — kanon qarori: loyihada migratsiyani Prisma Migrate boshqaradi (holat 36 dan), ikkinchi vosita qo'shilmaydi. node-pg-migrate faqat tajribada (kanon alohida bazada sinadi va ish oxirida uni o'chirdi). Commit yo'q.
O'zingiz sinab ko'rmoqchi bo'lsangiz — loyihadan tashqari papkada:
mkdir pgm-sinov && cd pgm-sinov && npm init -y
npm i -D node-pg-migrate@9.0.0 pg@8.23.1
mkdir migrations«SQL fayllar» va «JS migratsiya va noTransaction» bo'limlaridagi uch faylni migrations/ ga qo'ying, keyin DATABASE_URL=… npx node-pg-migrate up -m migrations va down. Alohida, bo'sh baza bilan — vazifalar loyihasi bazasida emas.
10. Real ishda
- Mikroservislar — har servis o'z bazasi va o'z migratsiyasi bilan; ko'p tilli kompaniyalarda dbmate yoki Flyway umumiy standart bo'ladi.
- Platforma jamoalari (DBA, SRE) ko'pincha Atlas yoki squawk kabi vositalar bilan migratsiyalarni avtomatik tekshiradi — dasturchi PR ochadi, lint xavfni ko'rsatadi.
- Ko'chish — ORM'dan voz kechish (masalan TypeORM → Kysely) migratsiya vositasini ham almashtiradi; bu — baseline bilan (Prisma Migrate chuqur dagi
resolve --appliedg'oyasi). - Intervyuda: "ORM'siz loyihada migratsiyani qanday boshqarasiz?", "Deklarativ va imperativ migratsiya farqi?", "Migratsiyani tranzaksiyaga o'rash har doim yaxshimi?".
Xulosa
- ORM'siz jamoaga faqat migratsiya vositasi kerak: fayllar, tartib, holat jadvali — node-pg-migrate, dbmate, graphile-migrate, Atlas, Flyway.
- node-pg-migrate sukut bo'yicha hamma kutilayotgan migratsiyalarni bitta tranzaksiyada qo'llaydi: kanonda uchinchisi yiqildi — hammasi bekor,
pgmigrationsbo'sh. --no-single-transaction— har biri o'z tranzaksiyasida, lekin baribir tranzaksiyada;CONCURRENTLYuchun JS migratsiyadapgm.noTransaction()(biz sinadik — ishladi).- Tranzaksiyasiz migratsiya atomik emas — bitta buyruq va
IF NOT EXISTS. - Deklarativ (Atlas) — kerakli holatdan reja; imperativ — qadamlar ro'yxati. Qoidalar (o'zgarmas fayl, alohida deploy qadami, xavfsiz DDL) har vositada bir xil.
Keyingi dars: MongoDB tuzilishi va vositalari — relatsion dunyodan hujjatlar bazasiga: kolleksiya, hujjat, BSON, mongosh va Compass.
Manbalar
- node-pg-migrate hujjati — CLI (
--no-single-transaction,--no-check-order),pgm.noTransaction(), SQL migratsiyalar: https://salsita.github.io/node-pg-migrate/ - dbmate README (
-- migrate:up,transaction:false): https://github.com/amacneil/dbmate (2026-10, sinalmagan) - graphile-migrate README (
current.sql,watch,commit): https://github.com/graphile/migrate (2026-10, sinalmagan) - Atlas hujjati — declarative va versioned workflows,
migrate lint: https://atlasgo.io/docs (2026-10, sinalmagan) - Flyway hujjati: https://documentation.red-gate.com/flyway; Liquibase: https://docs.liquibase.com (sinalmagan)
- Kanon o'lchovi (IlmHamroh, 2026-10; node-pg-migrate 9.0.0, PostgreSQL 18.6, 2026-10-25);
noTransactionvadown, SQL — biz ishga tushirdik (node-pg-migrate 9.0.0, PostgreSQL 17.6, Windows 11), 2026-10-25/27.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!