PostgreSQL ನ “cannot execute CREATE TABLE in a read-only transaction” ದೋಷವು ಈಗ ಅನೇಕ ತಂಡಗಳ ಮೈಗ್ರೇಷನ್ಗಳಿಗೆ (migrations) ಅಡಚಣೆಯಾಗುತ್ತಿದೆ, ಇದರಿಂದ ಸ್ಕೀಮಾಗಳು (schemas) ಅರ್ಧಕ್ಕೆ ಅನ್ವಯವಾಗುತ್ತವೆ ಮತ್ತು ಮೈಗ್ರೇಷನ್ ಇತಿಹಾಸದ ಟೇಬಲ್ಗಳು ಲಾಕ್ ಆಗುತ್ತವೆ. ಈ ವೈಫಲ್ಯವು ಸಾಮಾನ್ಯವಾಗಿ ಬರವಣಿಗೆಯ ಕಾರ್ಯಾಚರಣೆಯು (write operation) ಪ್ರೈಮರಿ (primary) ಬದಲಿಗೆ ರೆಪ್ಲಿಕಾ (replica) ಮೇಲೆ ನಡೆದಾಗ ಸಂಭವಿಸುತ್ತದೆ ಮತ್ತು ಇದು Flyway, Liquibase, Django ORM ಮತ್ತು ಅಂತಹ ಸ್ಕೀಮಾ ಬದಲಾವಣೆಗಳ ಮೇಲೆ ಅವಲಂಬಿತವಾಗಿರುವ ಯಾವುದೇ ಸಾಧನಗಳನ್ನು ಸ್ಥಗಿತಗೊಳಿಸುತ್ತದೆ.
ಈ ದೋಷ ಏಕೆ ಕಾಣಿಸಿಕೊಳ್ಳುತ್ತದೆ
ಟ್ರಾನ್ಸಾಕ್ಷನ್ ಅನ್ನು 'read-only' ಎಂದು ಗುರುತಿಸಿದಾಗ PostgreSQL ಎಲ್ಲಾ ಬರವಣಿಗೆಗಳು (writes), ಸ್ಕೀಮಾ ಬದಲಾವಣೆಗಳು ಮತ್ತು ಸೀಕ್ವೆನ್ಸ್ ಅಪ್ಡೇಟ್ಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ. ಮೈಗ್ರೇಷನ್ ಅಂತಹ ಸ್ಥಿತಿಗೆ ತಲುಪಲು ಸಾಮಾನ್ಯ ಕಾರಣಗಳು ಇಲ್ಲಿವೆ:
- Connection poolers (ಉದಾಹರಣೆಗೆ, PgBouncer) ಅಚಾತುರ್ಯದಿಂದ ಮೈಗ್ರೇಷನ್ ಕನೆಕ್ಷನ್ ಅನ್ನು ರೀಡ್ ರೆಪ್ಲಿಕಾ (read replica) ಗೆ ಕಳುಹಿಸುವುದು.
- Roles ដែល
default_transaction_read_onlyಪ್ಯಾರಾಮೀಟರ್ ಅನ್ನು ಡಿಫಾಲ್ಟ್ ಆಗಿ on ಎಂದು ಹೊಂದಿವೆ. - ಪ್ರತ್ಯೇಕ ರೀಡರ್ (reader) ಮತ್ತು ರೈಟರ್ (writer) URLಗಳನ್ನು ಹೊಂದಿರುವ Cloud endpoints; ರೀಡರ್ URL ಅನ್ನು ಬಳಸುವುದರಿಂದ (AWS RDS ಅಥವಾ Aurora ನಲ್ಲಿ ಸಾಮಾನ್ಯವಾಗಿ ಕಂಡುಬರುವಂತೆ) ಬರವಣಿಗೆಗಳು ರೆಪ್ಲಿಕಾಕ್ಕೆ ಹೋಗುತ್ತವೆ.
ಈ ಯಾವುದೇ ಪರಿಸ್ಥಿತಿಗಳು ಅನ್ವಯವಾದಾಗ, ಮೈಗ್ರೇಷನ್ ಪ್ರಕ್ರಿಯೆಯು ಟೇಬಲ್ಗಳನ್ನು ರಚಿಸಬಹುದು, ಕಾಲಮ್ಗಳನ್ನು ಸೇರಿಸಬಹುದು ಅಥವಾ ಸೀಕ್ವೆನ್ಸ್ ಅಪ್ಡೇಟ್ ಮಾಡಬಹುದು, ಆದರೆ ಕೊನೆಗೆ ಅದು ವಿಫಲವಾಗಿ ಡೇಟಾಬೇಸ್ ಅನ್ನು ಭಾಗಶಃ ಮೈಗ್ರೇಟ್ ಆದ ಸ್ಥಿತಿಯಲ್ಲಿ ಬಿಡುತ್ತದೆ.
ಟ್ರಾನ್ಸಾಕ್ಷನ್ ಒಳಗಿನ ತಕ್ಷಣದ ಪರಿಹಾರ
ನೀವು ಈಗಾಗಲೇ ಈ ದೋಷವನ್ನು ಎದುರಿಸುತ್ತಿದ್ದರೆ, ಉಳಿದ ಸೆಷನ್ (session) ಮೇಲೆ ಪರಿಣಾಮ ಬೀರದಂತೆ ಪ್ರಸ್ತುತ ಟ್ರಾನ್ಸಾಕ್ಷನ್ಗಾಗಿ 'read-only' ಫ್ಲಾಗ್ ಅನ್ನು ನೀವು ಓವರ್ರೈಡ್ (override) ಮಾಡಬಹುದು—ಕನೆಕ್ಷನ್ ಪೂಲ್ ಇತರ ಕೆಲಸಗಳಿಗಾಗಿ ಅದೇ ಸೆಷನ್ ಅನ್ನು ಮರುಬಳಕೆ ಮಾಡುವಾಗ ಇದು ಬಹಳ ಮುಖ್ಯವಾಗಿದೆ.
BEGIN;
SET LOCAL default_transaction_read_only = off;
SET TRANSACTION READ WRITE;
CREATE TABLE orders (id SERIAL PRIMARY KEY, total NUMERIC);
COMMIT;
SET LOCAL ಕೇವಲ ಟ್ರಾನ್ಸಾಕ್ಷನ್ ಅವಧಿಗೆ ಮಾತ್ರ ಸೆಟ್ಟಿಂಗ್ ಅನ್ನು ಬದಲಾಯಿಸುತ್ತದೆ. ಕೇವಲ SET ಅನ್ನು ಬಳಸುವುದರಿಂದ ಇಡೀ ಸೆಷನ್ನಲ್ಲಿ ಬದಲಾವಣೆಯು ಉಳಿಯುತ್ತದೆ, ಇದು ರೀಡ್-ಓನ್ಲಿ ಡಿಫಾಲ್ಟ್ ಅಗತ್ಯವಿರುವ ಇತರ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ಹಾಳುಮಾಡಬಹುದು.
ತಡೆಗಟ್ಟುವ ಕ್ರಮಗಳು
1. ನೀವು ಪ್ರೈಮರಿ ನೋಡ್ನಲ್ಲಿ (primary node) ಇದ್ದೀರಾ ಎಂದು ಪರಿಶೀಲಿಸಿ
ಯಾವುದೇ ಮೈಗ್ರೇಷನ್ ನಡೆಯುವ ಮೊದಲು ಈ ಕೆಳಗಿನ ಪರಿಶೀಲನೆಯನ್ನು ಸೇರಿಸಿ:
SELECT CASE WHEN pg_is_in_recovery() THEN 'REPLICA' ELSE 'PRIMARY' END;
ಫಲಿತಾಂಶವು REPLICA ಆಗಿದ್ದರೆ, ಮೈಗ್ರೇಷನ್ ಅನ್ನು ರದ್ದುಗೊಳಿಸಿ. pg_is_in_recovery() ಫಂಕ್ಷನ್ ಸ್ಟ್ಯಾಂಡ್ಬೈ ಸರ್ವರ್ನಲ್ಲಿ true ಎಂದು ನೀಡುತ್ತದೆ, ಇದು ನೀವು ರೀಡ್-ಓನ್ಲಿ ಕಾಪಿಗೆ ಬರೆಯಲು ಪ್ರಯತ್ನಿಸುತ್ತಿಲ್ಲ ಎಂಬುದನ್ನು ಖಚಿತಪಡಿಸುತ್ತದೆ.
2. ಮೀಸಲಾದ ಮೈಗ್ರೇಷನ್ ರೋಲ್ಗಳನ್ನು ಬಳಸಿ
ಡಿಫಾಲ್ಟ್ ಟ್ರಾನ್ಸಾಕ್ಷನ್ ಮೋಡ್ ಬರವಣಿಗೆಗೆ ಅನುಮತಿಸುವ (write-enabled) ಒಂದು ರೋಲ್ ಅನ್ನು ರಚಿಸಿ ಮತ್ತು ಅದಕ್ಕೆ ಅಗತ್ಯವಿರುವ ಅಧಿಕಾರಗಳನ್ನು ಮಾತ್ರ ನೀಡಿ:
- ಟಾರ್ಗೆಟ್ ಡೇಟಾಬೇಸ್ ಮೇಲೆ
CREATEಅಧಿಕಾರ. - ಮೈಗ್ರೇಷನ್ ಟೂಲ್ ಸೆಷನ್ ತೆರೆಯಲು ಅನುಮತಿಸಲು
CONNECTಅಧಿಕಾರ.
ಸಾಮಾನ್ಯ ಬಳಕೆದಾರರಿಗಾಗಿ ಕೆಲವೊಮ್ಮೆ ಹೊಂದಿಸಲಾಗುವ default_transaction_read_only = on ಎಂಬ ಅಟ್ರಿಬ್ಯೂಟ್ ಅನ್ನು ಈ ರೋಲ್ಗೆ ನೀಡಬೇಡಿ.
3. ಇನ್ಫ್ರಾಸ್ಟ್ರಕ್ಚರ್ ಅನ್ನು ರೈಟರ್ ಎಂಡ್ಪಾಯಿಂಟ್ಗೆ (writer endpoint) ಕಳುಹಿಸಿ
IaC ಸ್ಕ್ರಿಪ್ಟ್ಗಳಲ್ಲಿ (Terraform, CloudFormation, ಇತ್ಯಾದಿ), ಮೈಗ್ರೇಷನ್ ರನ್ನರ್ಗಳು ಕ್ಲಸ್ಟರ್ನ writer ಎಂಡ್ಪಾಯಿಂಟ್ ಅನ್ನು ಬಳಸುವಂತೆ ಕಾನ್ಫಿಗರ್ ಮಾಡಿ, ರೀಡರ್ ಎಂಡ್ಪಾಯಿಂಟ್ ಅನ್ನು ಅಲ್ಲ. ರೈಟರ್ ಎಂಡ್ಪಾಯಿಂಟ್ ಪ್ರೈಮರಿ ನೋಡ್ಗೆ ಸಂಪರ್ಕಿಸುತ್ತದೆ, ಆದರೆ ರೀಡರ್ ಎಂಡ್ಪಾಯಿಂಟ್ ಬರವಣಿಗೆಗಳನ್ನು ತಿರಸ್ಕರಿಸುವ ರೆಪ್ಲಿಕಾಕ್ಕೆ ಸಂಪರ್ಕಿಸುತ್ತದೆ.
4. CI/CD ಗೇಟ್ ಅನ್ನು ಸೇರಿಸಿ
ನಿಮ್ಮ ಪೈಪ್ಲೈನ್ನಲ್ಲಿ (GitHub Actions, GitLab CI, ಇತ್ಯಾದಿ) pg_is_in_recovery() ಕ್ವೆರಿಯನ್ನು ರನ್ ಮಾಡುವ ಶೆಲ್ ಸ್ಟೆಪ್ ಅನ್ನು ಸೇರಿಸಿ. ಇದು true ಎಂದು ನೀಡಿದರೆ, ನಿಯೋಜನೆಯನ್ನು (deployment) ಮೊದಲೇ ನಿಲ್ಲಿಸಲು નોನ್-ಜೀರೋ (non-zero) ಸ್ಟೇಟಸ್ನೊಂದಿಗೆ ಕೆಲಸದಿಂದ ಹೊರಬನ್ನಿ.
if psql $DATABASE_URL -c "SELECT pg_is_in_recovery()" | grep -q t; then
echo "Connected to replica – aborting migration"
exit 1
fi
5. ಮೈಗ್ರೇಷನ್-ಟೂಲ್ ರಿಟ್ರೈಗಳನ್ನು (retries) ಟ್ಯೂನ್ ಮಾಡಿ
Flyway ನಂತಹ ಸಾಧನಗಳು ಹೆಚ್ಚಾಗಿ ಕನೆಕ್ಷನ್ಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ರಿಟ್ರೈ ಮಾಡುತ್ತವೆ. Flyway 9+ ಗಾಗಿ flyway.connectRetries=0 ಎಂದು ಸೆಟ್ ಮಾಡಿ. ಇದು ಸಾಧನವು ಪದೇ ಪದೇ ರೆಪ್ಲಿಕಾ ಮೇಲೆ ಪ್ರಭಾವ ಬೀದದಂತೆ ತಡೆಯುತ್ತದೆ, ಇಲ್ಲದಿದ್ದರೆ ಇದು ರೆಪ್ಲಿಕೇಶನ್ ವಿಳಂಬವನ್ನು (replication lag) ಹೆಚ್ಚಿಸಬಹುದು ಮತ್ತು ಸಂಪನ್ಮೂಲಗಳನ್ನು ವ್ಯರ್ಥ ಮಾಡಬಹುದು.
ಮುಂದೆ ಗಮನಿಸಬೇಕಾದವುಗಳು
- Replication lag metrics: ಹೆಚ್ಚುತ್ತಿರುವ ವಿಳಂಬವು ಮೈಗ್ರೇಷನ್ ಅಚಾತುರ್ಯದಿಂದ ರೆಪ್ಲಿಕಾವನ್ನು ಗುರಿಯಾಗಿಸಿಕೊಂಡಿದೆ ಎಂಬುದನ್ನು ಸೂಚಿಸಬಹುದು, ಇದು ಬರವಣಿಗೆಯ ಪ್ರಯತ್ನಗಳು ಕ್ಯೂ (queue) ಆಗಲು ಕಾರಣವಾಗುತ್ತದೆ.
- Connection-pooler routing rules: ಪೂಲರ್ ಕಾನ್ಫಿಗರೇಶನ್ಗಳು ಮೈಗ್ರೇಷನ್ ಟ್ರಾಫಿಕ್ ಅನ್ನು ಸ್ಪಷ್ಟವಾಗಿ ಪ್ರೈಮರಿ ಹೋಸ್ಟ್ಗೆ ಕಳುಹಿಸುತ್ತಿವೆ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ.
- Role defaults after upgrades: ಡೇಟಾಬೇಸ್ ಅಪ್ಗ್ರೇಡ್ಗಳು ಕೆಲವೊಮ್ಮೆ ರೋಲ್ ಪ್ಯಾರಾಮೀಟರ್ಗಳನ್ನು ಮರುಹೊಂದಿಸುತ್ತವೆ; ಪ್ರಮುಖ ಆವೃತ್ತಿ ಬದಲಾವಣೆಗಳ ನಂತರ
default_transaction_read_onlyಅನ್ನು ಮರು-ಪರಿಶೀಲಿಸಿ.
ಸಾರಾಂಶವೆಂದರೆ: ರೀಡ್-ಓನ್ಲಿ ಟ್ರಾನ್ಸಾಕ್ಷನ್ ದೋಷವು ಅಪರೂಪವಾಗಿ PostgreSQL ಬಗ್ ಆಗಿರುತ್ತದೆ; ಇದು ತಪ್ಪು ನೋಡ್ಗೆ ಟ್ರಾಫಿಕ್ ಕಳುಹಿಸುವುದು ಅಥವಾ ರೋಲ್ ಅನ್ನು ತಪ್ಪಾಗಿ ಕಾನ್ಫಿಗರ್ ಮಾಡುವುದರ ಲಕ್ಷಣವಾಗಿದೆ. ನೋಡ್ ರೋಲ್ ಅನ್ನು ಪರಿಶೀಲಿಸುವ ಮೂಲಕ, ಮೀಸಲಾದ ಮೈಗ್ರೇಷನ್ ಖಾತೆಗಳನ್ನು ಬಳಸುವ ಮೂಲಕ ಮತ್ತು ನಿಮ್ಮ CI/CD ಪೈಪ್ಲೈನ್ ಅನ್ನು ಬಲಪಡಿಸುವ ಮೂಲಕ, ನೀವು ಮೈಗ್ರೇಷನ್ಗಳನ್ನು ಸುಗಮವಾಗಿ ನಡೆಸಬಹುದು ಮತ್ತು ಮುಂದಿನ ಅಭಿವೃದ್ಧಿಯನ್ನು ಕುಂಠಿತಗೊಳಿಸುವ ಅರ್ಧಕ್ಕೆ ಅನ್ವಯವಾದ ಸ್ಕೀಮಾಗಳನ್ನು ತಪ್ಪಿಸಬಹುದು.
