PostgreSQL ની “cannot execute CREATE TABLE in a read-only transaction” ભૂલ હવે ઘણી ટીમો માટે માઈગ્રેશન (migrations) માં અવરોધ ઊભો કરી રહી છે, જેના કારણે સ્કીમા (schemas) અડધા લાગુ થાય છે અને માઈગ્રેશન હિસ્ટ્રી ટેબલ્સ લોક થઈ જાય છે. આ નિષ્ફળતા સામાન્ય રીતે ત્યારે જોવા મળે છે જ્યારે રાઈટ ઓપરેશન (write operation) પ્રાઈમરીને બદલે રેપ્લિકા (replica) પર જાય છે, અને તે Flyway, Liquibase, Django ORM અને સમાન સાધનો જે સ્કીમા ફેરફારો પર આધાર રાખે છે તેને અટકાવી દે છે.

આ ભૂલ શા માટે દેખાય છે

જ્યારે ટ્રાન્ઝેક્શનને read-only તરીકે માર્ક કરવામાં આવે ત્યારે PostgreSQL તમામ writes, સ્કીમા ફેરફારો અને sequence અપડેટ્સ અટકાવી દે છે. માઈગ્રેશન આ સ્થિતિમાં પહોંચવાના સૌથી સામાન્ય કારણો નીચે મુજબ છે:

  • Connection poolers (દા.ત., PgBouncer) જે અજાણતા માઈગ્રેશન કનેક્શનને read replica પર મોકલે છે.
  • Roles જેમાં default_transaction_read_only પેરામીટર ડિફોલ્ટ તરીકે on સેટ કરેલું હોય છે.
  • Cloud endpoints જે અલગ reader અને writer URLs પ્રદાન કરે છે; reader URL નો ઉપયોગ કરવાથી (જેમ કે AWS RDS અથવા Aurora માં સામાન્ય છે) writes રેપ્લિકા પર જાય છે.

જ્યારે આમાંથી કોઈપણ સ્થિતિ લાગુ પડે છે, ત્યારે માઈગ્રેશન પ્રક્રિયા ટેબલ્સ બનાવી શકે છે, કોલમ ઉમેરી શકે છે અથવા sequences અપડેટ કરી શકે છે, પરંતુ અંતે તે અટકી જાય છે, જેનાથી ડેટાબેઝ અપૂર્ણ માઈગ્રેશન સ્થિતિમાં રહી જાય છે.

ટ્રાન્ઝેક્શનની અંદર તાત્કાલિક નિવારણ

જો તમે આ ભૂલનો સામનો કરી ચૂક્યા હોવ, તો તમે બાકીના સેશનને અસર કર્યા વિના વર્તમાન ટ્રાન્ઝેક્શન માટે read-only ફ્લેગને ઓવરરાઈડ કરી શકો છો—જ્યારે કનેક્શન પૂલ અન્ય કામ માટે સમાન સેશનનો ફરીથી ઉપયોગ કરે છે ત્યારે આ ખૂબ જ મહત્વપૂર્ણ છે.

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 નો ઉપયોગ કરવાથી આખા સેશન માટે ફેરફાર કાયમી થઈ જશે, જે અન્ય એવા ઓપરેશન્સને તોડી શકે છે જેને કાયદેસર રીતે read-only ડિફોલ્ટની જરૂર હોય છે.

નિવારક પગલાં

1. તમે પ્રાઈમરી નોડ પર છો તેની ખાતરી કરો

કોઈપણ માઈગ્રેશન ચલાવતા પહેલા એક ઝડપી ચેક ઉમેરો:

SELECT CASE WHEN pg_is_in_recovery() THEN 'REPLICA' ELSE 'PRIMARY' END;

જો પરિણામ REPLICA હોય, તો માઈગ્રેશન અટકાવી દો. pg_is_in_recovery() ફંક્શન સ્ટેન્ડબાય સર્વર પર true રિટર્ન કરે છે, જે ખાતરી આપે છે કે તમે read-only કોપીમાં લખવાનો પ્રયાસ નથી કરી રહ્યા.

2. સમર્પિત (dedicated) માઈગ્રેશન રોલ્સનો ઉપયોગ કરો

એવો રોલ બનાવો જેનું ડિફોલ્ટ ટ્રાન્ઝેક્શન મોડ write-enabled હોય, અને તેને ફક્ત જરૂરી પ્રિવિલેજ જ આપો:

  • CREATE target ડેટાબેઝ પર.
  • CONNECT માઈગ્રેશન ટૂલને સેશન ખોલવા દેવા માટે.

આ રોલને default_transaction_read_only = on એટ્રિબ્યુટ આપવાનું ટાળો, જે ક્યારેક સામાન્ય હેતુના વપરાશકર્તાઓ માટે સેટ કરવામાં આવે છે.

3. ઇન્ફ્રાસ્ટ્રક્ચરને writer endpoint પર નિર્દેશિત કરો

IaC સ્ક્રિપ્ટ્સ (Terraform, CloudFormation, વગેરે) માં, માઈગ્રેશન રનર્સને reader endpoint ને બદલે ક્લસ્ટરના writer endpoint નો ઉપયોગ કરવા માટે કોન્ફિગર કરો. Writer endpoint પ્રાઈમરી નોડ પર રિઝોલ્વ થાય છે, જ્યારે reader endpoint રેપ્લિકા પર રિઝોલ્વ થાય છે જે writes ને રિજેક્ટ કરશે.

4. CI/CD ગેટ ઉમેરો

તમારા પાઇપલાઇનમાં (GitHub Actions, GitLab CI, વગેરે) એક શેલ સ્ટેપ ઉમેરો જે pg_is_in_recovery() ક્વેરી ચલાવે છે. જો તે true રિટર્ન કરે, તો ડિપ્લોયમેન્ટ વહેલું રોકવા માટે નોન-ઝીરો સ્ટેટસ સાથે જોબમાંથી એક્ઝિટ કરો.

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 જેવા સાધનો ઘણીવાર કનેક્શનને આપમેળે ફરીથી પ્રયાસ (retry) કરે છે. Flyway 9+ માટે flyway.connectRetries=0 સેટ કરો. આ સાધનને વારંવાર રેપ્લિકા પર હિટ થતા અટકાવશે, જે અન્યથા રેપ્લિકેશન લેગ (replication lag) વધારી શકે છે અને સંસાધનોનો બગાડ કરી શકે છે.

આગળ શું ધ્યાન રાખવું

  • Replication lag metrics: વધતો જતો લેગ એ સૂચવી શકે છે કે માઈગ્રેશન અજાણતા રેપ્લિકાને ટાર્ગેટ કરી રહ્યું છે, જેના કારણે write પ્રયાસો કતારમાં (queued) રહી જાય છે.
  • Connection-pooler routing rules: ખાતરી કરો કે પૂલર કોન્ફિગરેશન સ્પષ્ટપણે માઈગ્રેશન ટ્રાફિકને પ્રાઈમરી હોસ્ટ પર રૂટ કરે છે.
  • Role defaults after upgrades: ડેટાબેઝ અપગ્રેડ્સ ક્યારેક રોલ પેરામીટર્સ રીસેટ કરે છે; મુખ્ય વર્ઝન ફેરફારો પછી default_transaction_read_only ને ફરીથી ઓડિટ કરો.

ટૂંકમાં: read-only ટ્રાન્ઝેક્શન ભૂલ ભાગ્યે જ PostgreSQL બગ છે; તે ખોટા નોડ પર ટ્રાફિક મોકલવામાં આવતો હોય અથવા રોલ ખોટી રીતે કોન્ફિગર થયેલ હોય તેનું લક્ષણ છે. નોડ રોલ તપાસીને, સમર્પિત માઈગ્રેશન એકાઉન્ટ્સનો ઉપયોગ કરીને અને તમારી CI/CD પાઇપલાઇનને મજબૂત બનાવીને, તમે માઈગ્રેશન સરળતાથી ચલાવી શકો છો અને અપૂર્ણ લાગુ થયેલા સ્કીમાથી બચી શકો છો જે આગળના ડેવલપમેન્ટને અવરોધે છે.