การย้ายฐานข้อมูลด้วย Go บน Mac

เมื่อทำงานกับฐานข้อมูล การโยกย้ายสคีมาเป็นงานสำคัญอย่างหนึ่งที่เรามักจะต้องทำตลอดอายุการใช้งานของแอปพลิเคชันเพื่อปรับให้เข้ากับความต้องการทางธุรกิจใหม่

ในบทความนี้ เราจะเรียนรู้วิธีการเขียนและเรียกใช้การโยกย้ายสคีมาฐานข้อมูลใน Go โดยใช้ไลบรารี golang-migrate


ข้อกำหนดเบื้องต้น


ข้อกำหนดสำหรับบทความนี้คือ คุณต้องติดตั้ง Go บนคอมพิวเตอร์ของคุณ และได้ทำตามบทความ ติดตั้ง Go บน Mac และ ติดตั้งและใช้ Docker บน Mac มาก่อน


ติดตั้งและใช้งาน Homebrew บน Mac


ติดตั้ง golang-migrate


Golang-migrate ทำงานร่วมกับเครื่องมือฐานข้อมูลต่างๆ เช่น postgres, mysql, mongo, cockroach ฯลฯ เปิด เอกสาร CLI นี้เพื่อดูวิธีการติดตั้ง ฉันใช้ Mac ดังนั้นฉันจะใช้ Homebrew

brew install golang-migrate


Migrate ให้คำสั่งหลายอย่างแก่เรา:

  • อันแรกคือ create ซึ่งเราสามารถใช้สร้างไฟล์การโยกย้ายใหม่
  • อันที่ 2 คือ goto ซึ่งจะย้าย schema ไปยังเวอร์ชันเฉพาะ
  • จากนั้น คำสั่ง upor down เพื่อปรับใช้การย้ายข้อมูลขึ้นหรือลงทั้งหมดหรือ N


มีคำสั่งอื่นๆ อีกหลายคำสั่ง แต่โดยส่วนใหญ่ เราจะทำงานกับcreate, , upและdown

เอาล่ะ ติดตั้งการโยกย้ายสำเร็จแล้ว


Create a new migration


ตกลง ตอนนี้ฉันกำลังจะสร้างโฟลเดอร์ใหม่ simple_bank สำหรับโครงการ Simple Bank ของเรา


และข้างใน ฉันจะสร้างโฟลเดอร์ใหม่ db/migration เพื่อเก็บไฟล์การย้ายข้อมูลทั้งหมดของเรา

จากนั้น มาสร้างไฟล์การโยกย้ายครั้งแรกเพื่อเริ่มต้นสคีมาฐานข้อมูลของ Simple Bank

เปิด Terminal เริ่มด้วย migrate create จากนั้นนามสกุลของไฟล์จะเป็น sql และไดเร็กทอรีที่จะจัดเก็บก็ db/migration ด้วยคำสั่ง

migrate create -ext sql -dir db/migration -seq init_schema


เราใช้แฟล็ก -seq เพื่อสร้างหมายเลขเวอร์ชันตามลำดับสำหรับไฟล์การย้ายข้อมูล และสุดท้ายชื่อการโยกย้ายซึ่ง init_schema ในกรณีนี้

อย่างที่คุณเห็น มีการสร้างไฟล์การโยกย้าย 2 ไฟล์สำหรับเรา ทั้งคู่มีเวอร์ชัน 1 อยู่ในคำนำหน้าของชื่อไฟล์ แต่ส่วนต่อท้ายต่างกัน: 1 ไฟล์เป็น up และอีกไฟล์หนึ่งคือ down. ทำไม?

การโยกย้ายขึ้น/ลง


โดยพื้นฐานแล้วมันเป็นแนวทางปฏิบัติที่ดีที่สุดเมื่อเขียนการย้ายฐานข้อมูล สคริปต์ up ถูกเรียกใช้เพื่อทำการเปลี่ยนแปลงไปข้างหน้ากับสคีมา และสคริปต์ down จะทำงานถ้าเราต้องการย้อนกลับการเปลี่ยนแปลงที่ทำโดยสคริปต์ up

ดังนั้นเมื่อเรารัน migrate up คำสั่ง up ไฟล์สคริปต์ภายในโฟลเดอร์ db/migration จะถูกรันตามลำดับของเวอร์ชันนำหน้า


ในทางกลับกัน เมื่อเรารัน migrate down คำสั่ง ไฟล์ down-script ภายใน db/migration โฟลเดอร์จะถูกรันตามลำดับโดยกลับกันของเวอร์ชันนำหน้า


เรามาเปิด simple_bank.sql ไฟล์ที่เราสร้างขึ้นจากบทความ ติดตั้งและใช้ Docker บน Mac โดยจะคัดลอกเนื้อหาทั้งหมดของไฟล์นี้แล้ววางลงในไฟล์ init_schema.up.sql

CREATE TABLE "accounts" (
  "id" bigserial PRIMARY KEY,
  "owner" varchar NOT NULL,
  "balance" bigint NOT NULL,
  "currency" varchar NOT NULL,
  "created_at" timestamptz NOT NULL DEFAULT (now())
);

CREATE TABLE "entries" (
  "id" bigserial PRIMARY KEY,
  "account_id" bigint NOT NULL,
  "amount" bigint NOT NULL,
  "created_at" timestamptz NOT NULL DEFAULT (now())
);

CREATE TABLE "transfers" (
  "id" bigserial PRIMARY KEY,
  "from_account_id" bigint NOT NULL,
  "to_account_id" bigint NOT NULL,
  "amount" bigint NOT NULL,
  "created_at" timestamptz NOT NULL DEFAULT (now())
);

ALTER TABLE "entries" ADD FOREIGN KEY ("account_id") REFERENCES "accounts" ("id");

ALTER TABLE "transfers" ADD FOREIGN KEY ("from_account_id") REFERENCES "accounts" ("id");

ALTER TABLE "transfers" ADD FOREIGN KEY ("to_account_id") REFERENCES "accounts" ("id");

CREATE INDEX ON "accounts" ("owner");

CREATE INDEX ON "entries" ("account_id");

CREATE INDEX ON "transfers" ("from_account_id");

CREATE INDEX ON "transfers" ("to_account_id");

CREATE INDEX ON "transfers" ("from_account_id", "to_account_id");

COMMENT ON COLUMN "entries"."amount" IS 'can be negative or positive';

COMMENT ON COLUMN "transfers"."amount" IS 'must be positive';


สำหรับไฟล์ init_schema.down.sql เราควรคืนค่าการเปลี่ยนแปลงที่ทำโดยสคริปต์ up ในกรณีนี้ สคริปต์ up จะสร้าง 3 ตาราง คือ: accounts, , transfers และ entries ดังนั้นสคริปต์ down ควรลบทั้งหมด เราใช้ DROP TABLE แบบสอบถามเพื่อจุดประสงค์นี้

DROP TABLE IF EXISTS entries;
DROP TABLE IF EXISTS transfers;
DROP TABLE IF EXISTS accounts;

ที่นี่เราวางตาราง entries และ transfers ก่อนที่จะวางตาราง accounts เนื่องจากมีข้อจำกัดของคีย์ต่างประเทศ entries และ transfers ที่อ้างอิงบันทึก accounts

ตกลง ตอนนี้สคริปต์การย้ายข้อมูลของเราพร้อมแล้ว ลองเรียกใช้พวกเขา

ตรวจสอบสถานะคอนเทนเนอร์ของ postgres


แต่ก่อนหน้านั้นเราควรตรวจสอบว่าคอนเทนเนอร์ postgres ของเรายังทำงานอยู่หรือไม่:

docker ps


ฉันจะแสดงคำสั่ง docker เพิ่มเติมเพื่อทำงานกับคอนเทนเนอร์ หากเราต้องการหยุดคอนเทนเนอร์ที่ทำงานอยู่ เราจะใช้ docker stop กับชื่อคอนเทนเนอร์หรือ ID

docker stop postgres12


หลังจากนี้ถ้าเรารัน docker ps เราจะไม่เห็นคอนเทนเนอร์ postgres อีกต่อไปเพราะไม่ได้ทำงาน ในการแสดงรายการคอนเทนเนอร์ทั้งหมด โดยไม่คำนึงถึงสถานะการทำงาน เราสามารถเรียกใช้:

docker ps -a


ตอนนี้เราเห็น postgres คอนเทนเนอร์ของเราพร้อมสถานะ Exited


หากต้องการเปิดใช้งานอีกครั้ง เราเพียงแค่ต้องเรียกใช้: docker star tและ ส่งต่อชื่อคอนเทนเนอร์หรือ ID

docker start postgres12


และตอนนี้คอนเทนเนอร์ postgres12 เริ่มทำงานแล้ว


เข้าถึง shell คอนเทนเนอร์ของ postgres


เราสามารถเข้าถึงเปลือกของมันได้ด้วยคำสั่ง docker exec เนื่องจากเราใช้ postgres alpine image เราไม่มี shell /bin/bash เหมือนใน ubuntu ดังนั้นเราจึงใช้ shell /bin/sh แทน:

docker exec -it postgres12 /bin/sh

ภายในเชลล์ เราสามารถเข้าถึงคำสั่ง linux มาตรฐานทั้งหมดได้ เช่น คำสั่ง ls จะแสดง List ของ File และ Directory ใน Path ที่ใช้งานอยู่

ls -l

และเนื่องจากนี่คือคอนเทนเนอร์ postgres มันจึงให้คำสั่ง CLI บางอย่างแก่เราในการโต้ตอบกับเซิร์ฟเวอร์ postgres โดยตรงจาก shell


Create/drop ฐานข้อมูลภายในคอนเทนเนอร์ postgres


เราต้องสร้างฐานข้อมูลก่อนจึงจะสามารถเรียกใช้การโยกย้ายครั้งแรกได้

ให้เรียกใช้คำสั่ง createdb ภายในเชลล์ของคอนเทนเนอร์ postgres เพื่อสร้างฐานข้อมูลใหม่สำหรับ Simple Bank ของเรา:

createdb --username=root --owner=root simple_bank

  • เราใช้ตัวเลือก –username เพื่อบอกว่าเรากำลังเชื่อมต่อในฐานะ root ผู้ใช้
  • และตัวเลือก –owner ที่จะบอกว่าฐานข้อมูลที่เราจะสร้างจะเป็นของ root ผู้ใช้ด้วยเช่นกัน
  • อาร์กิวเมนต์สุดท้ายคือชื่อฐานข้อมูล simple_bank

ตกลง เราสร้างฐานข้อมูลแล้ว และสามารถเข้าถึงคอนโซลได้ด้วยคำสั่ง psql

นอกจากนี้เรายังสามารถลบฐานข้อมูลโดยใช้ dropdb คำสั่งและส่งต่อในชื่อของฐานข้อมูล

dropdb simple_bank

เราใช้คำสั่ง exit เพื่อออกจาก shell คอนเทนเนอร์

exit


Create/drop ฐานข้อมูลนอกคอนเทนเนอร์ postgres


ตอนนี้จากภายนอกคอนเทนเนอร์ เราสามารถเรียกใช้ createdb ด้วยคำสั่ง docker exec ได้โดยตรง

docker exec -it postgres12 createdb --username=root --owner=root simple_bank

และเข้าถึงคอนโซลฐานข้อมูลโดยไม่ต้องผ่าน shell คอนเทนเนอร์

docker exec -it postgres12 psql -U root simple_bank

เราใช้คำสั่ง exit เพื่อออกจาก shell

exit

หยุดคอนเทนเนอร์ postgres ปัจจุบัน

docker stop postgres12

คอนเทนเนอร์หยุดทำงาน ฉันจะลบมันออกให้หมดโดยใช้คำสั่ง docker rm

docker rm postgres12


เราจะไม่เห็นคอนเทนเนอร์ postgres อีกต่อไปเพราะไม่ได้ทำงาน ตรวจสอบได้จากคำสั่ง

docker ps -a


เขียน Makefile


ตอนนี้ฉันกำลังจะสร้าง Makefile ในโครงการของเรา จากนั้นเพิ่มคำสั่ง createdb เพื่อสร้างฐานข้อมูลธนาคารอย่างง่าย และคำสั่ง dropdb เพื่อลบมัน ก่อนอื่น ต้องติดตั้ง Make

เมื่อทำงานในทีม คำสั่งเหล่านี้จะเป็นประโยชน์สำหรับเพื่อนร่วมทีมของคุณในการตั้งค่าโปรเจ็กต์บนเครื่องในพื้นที่ของตนเพื่อการพัฒนาได้อย่างง่ายดาย

มาเพิ่มคำสั่งที่เราใช้ในการเริ่มคอนเทนเนอร์ postgres ในการบรรยายครั้งก่อนไปยัง Makefile ด้วย

สร้างไฟล์ Makefile เขียนโค้ดดังนี้

postgres:
	docker run --name postgres12 -p 5432:5432 -e POSTGRES_USER=root -e POSTGRES_PASSWORD=secret -d postgres:12-alpine

createdb:
	docker exec -it postgres12 createdb --username=root --owner=root simple_bank

dropdb:
	docker exec -it postgres12 dropdb simple_bank

.PHONY: postgres createdb dropdb


ทดสอบใช้คำสั่ง

make postgres


คอนเทนเนอร์ postgres ใหม่จะเริ่มต้นขึ้น และทดลองใช้คำสั่ง make createdb เพื่อสร้างฐานข้อมูล simple_bank

make createdb


ตรวจสอบการสร้าง ฐานข้อมูล simple_bank ได้จากคำสั่ง

docker ps


ดูฐานข้อมูลด้วย TablePlus


เราได้สร้างฐานข้อมูลแล้ว มาเชื่อมต่อกับมันโดยใช้ TablePlus

การเชื่อมต่อที่เราตั้งค่าในครั้งก่อน จะนำเราไปยังฐานข้อมูล root


เราสามารถคลิกที่ไอคอนฐานข้อมูลเพื่อเปิดฐานข้อมูล simple_bank ใหม่ของเรา


คุณสามารถดู 2 ฐานข้อมูล ได้ที่นี่: root และ simple_bank และ สำหรับตอนนี้ฐานข้อมูล simple_bank ว่างเปล่า


เรียกใช้การโยกย้าย migration


กลับไปที่เทอร์มินัล แล้วเรียกใช้การย้ายข้อมูลครั้งแรก

เริ่มด้วย migrate จากนั้นเราใช้ – path ตัวเลือกเพื่อระบุโฟลเดอร์ที่มีไฟล์การโยกย้ายของเรา ซึ่งก็คือ db/migration

migrate -path db/migration -database "postgresql://root:secret@localhost:5432/simple_bank" -verbose up


ตัวเลือกนี้ -database ใช้เพื่อระบุ URL ไปยังเซิร์ฟเวอร์ฐานข้อมูล

  • เราใช้ postgres ดังนั้นชื่อไดรเวอร์คือ postgresql
  • จากนั้นชื่อผู้ใช้คือ root
  • รหัสผ่านคือ secret
  • ที่อยู่คือ localhost พอร์ต 5432
  • และชื่อฐานข้อมูลคือ simple_bank.

เราใช้ตัวเลือก -verbose เพื่อขอให้โยกย้ายเพื่อพิมพ์การบันทึกแบบละเอียด

และสุดท้ายเราใช้อาร์กิวเมนต์ up เพื่อบอกให้ migrate รันคำสั่ง migrate up

เรามีข้อผิดพลาด: error: pq: SSL is not enabled on the server เพราะไม่ได้เปิดใช้งาน SSL บนเซิร์ฟเวอร์ นั่นเป็นเพราะคอนเทนเนอร์ postgres ของเราไม่ได้เปิดใช้งาน SSL เป็นค่าเริ่มต้น

ดังนั้นเราควรเพิ่มพารามิเตอร์ sslmode=disable ลงใน URL ฐานข้อมูล ตอนนี้รันคำสั่งนี้:

migrate -path db/migration -database "postgresql://root:secret@localhost:5432/simple_bank?sslmode=disable" -verbose up


และการโยกย้ายก็สำเร็จ!

หากเรารีเฟรชฐานข้อมูล simple_bank ใน TablePlus เราจะเห็นตาราง 4 ตาราง คือ : accounts, entries, , transfers และ schema_migrations


ตาราง schema_migrations จะจัดเก็บเวอร์ชันการโยกย้ายที่ใช้ล่าสุด ซึ่งในกรณีของเราคือเวอร์ชัน 1 เนื่องจากเราเรียกใช้ไฟล์การย้ายข้อมูลเพียงไฟล์เดียว

คอลัมน์ dirty นี้จะบอกเราว่าการโยกย้ายครั้งล่าสุดล้มเหลวหรือไม่ หากล้มเหลว เราต้องแก้ไขปัญหาด้วยตนเองเพื่อให้สถานะฐานข้อมูลสะอาดก่อนที่จะพยายามเรียกใช้เวอร์ชันการโยกย้ายอื่นๆ


เพิ่มการโยกย้ายขึ้น/ลงไปยัง Makefile


ตกลงตอนนี้ฉันจะเพิ่ม migrateup และ migratedown ในคำสั่ง Makefile:

postgres:
	docker run --name postgres12 -p 5432:5432 -e POSTGRES_USER=root -e POSTGRES_PASSWORD=secret -d postgres:12-alpine

createdb:
	docker exec -it postgres12 createdb --username=root --owner=root simple_bank

dropdb:
	docker exec -it postgres12 dropdb simple_bank

migrateup:
	migrate -path db/migration -database "postgresql://root:secret@localhost:5432/simple_bank?sslmode=disable" -verbose up

migratedown:
	migrate -path db/migration -database "postgresql://root:secret@localhost:5432/simple_bank?sslmode=disable" -verbose down

.PHONY: postgres createdb dropdb migrateup migratedown


ใช้คำสั่ง make migratedown

make migratedown

และกลับไปที่ TablePlus และรีเฟรช ตารางทั้งหมดจะหายไป ยกเว้นตาราง schema_migrations


ใช้คำสั่ง make migrateup

make migrateup

จากนั้นรีเฟรช TablePlus ตารางทั้งหมดจะกลับมาอีกครั้ง

credit : https://dev.to/techschoolguru/

Leave a Reply

Your email address will not be published. Required fields are marked *