ഒരു പ്രൊഡക്ഷൻ PostgreSQL ഡിപ്ലോയ്മെന്റ് തകരാറിലായി. ഒരു ഡെവലപ്പർ നിലവിലുള്ള ഒരു ഫങ്ക്ഷനിൽ CREATE OR REPLACE FUNCTION ഉപയോഗിച്ച് ഒരു ഓപ്ഷണൽ ആർഗ്യുമെന്റ് ചേർത്തതിനെത്തുടർന്നാണ് ഇത് സംഭവിച്ചത്. ഈ മാറ്റം കാരണം ഒരേ പേരുള്ള രണ്ട് ഫങ്ക്ഷനുകൾ ഉണ്ടാവുകയും, ഡാറ്റാബേസ് “function is not unique” എന്ന എറർ നൽകുകയും API 400 എറർ കാണിക്കുകയും ചെയ്തു. ഒരു ചെറിയ മൈഗ്രേഷൻ തെറ്റ് എങ്ങനെ ഒരു ലൈവ് സ്കീമയെ നിശബ്ദമായി നശിപ്പിക്കാം എന്നും കോഡ് തലത്തിലുള്ള പരിശോധനകൾ മാത്രം മതിയാകില്ലെന്നും ഈ സംഭവം കാണിച്ചുതരുന്നു.
എന്താണ് സംഭവിച്ചത്
ഒരു സ്റ്റോർഡ് പ്രൊസീജറിലേക്ക് ഒരു അധിക ഓപ്ഷണൽ പാരാമീറ്റർ കൂടി ചേർക്കാൻ ടീമിന് ആവശ്യമായിരുന്നു. പഴയ ഡെഫനിഷൻ ഓവർറൈറ്റ് ചെയ്യപ്പെടുമെന്ന് കരുതി അവർ CREATE OR REPLACE FUNCTION … എന്ന കമാൻഡ് പ്രവർത്തിപ്പിച്ചു. ആർഗ്യുമെന്റ് ലിസ്റ്റ് കൃത്യമായി ഒത്തുപോകുമ്പോൾ മാത്രമേ PostgreSQL ഒരു ഫങ്ക്ഷൻ റീപ്ലേസ് ചെയ്യുകയുള്ളൂ. സിഗ്നേച്ചർ മാറ്റുന്നത് പഴയതിനെ മാറ്റാതെ തന്നെ ഒരു പുതിയ ഫങ്ക്ഷൻ എൻട്രി സൃഷ്ടിക്കുന്നു.
പുതിയ ആർഗ്യുമെന്റിന് ഒരു ഡിഫോൾട്ട് വാല്യൂ ഉള്ളതിനാൽ, പഴയ രീതിയിൽ ആർഗ്യുമെന്റുകൾ നൽകുന്നവർക്ക് രണ്ട് ഡെഫനിഷനുകളിലും മാച്ച് ആകാൻ സാധിക്കും. ഏത് ഫങ്ക്ഷൻ പ്രവർത്തിപ്പിക്കണമെന്ന് തീരുമാനിക്കാൻ കഴിയാതെ PostgreSQL “function is not unique” എന്ന എറർ നൽകി, ഇത് API-ൽ നിന്ന് 400 റെസ്പോൺസായി പുറത്തുവന്നു.
കോഡ് റെപ്പോസിറ്ററിയിൽ ഒരു ഡെഫനിഷൻ മാത്രമേ ഉണ്ടായിരുന്നുള്ളൂ, സോഴ്സ് ട്രീ സ്കാൻ ചെയ്യുന്ന ഒരു കസ്റ്റം സ്ക്രിപ്റ്റും ഡ്യൂപ്ലിക്കേറ്റുകൾ റിപ്പോർട്ട് ചെയ്തില്ല. ഡ്യൂപ്ലിക്കേറ്റ് ഡാറ്റാബേസിൽ മാത്രമായിരുന്നു ഉണ്ടായിരുന്നത്, ഒരു പഴയ മൈഗ്രേഷൻ ഫയൽ സെർവറിൽ വീണ്ടും പ്രവർത്തിപ്പിച്ചപ്പോഴാണ് ഇത് സംഭവിച്ചത്.
എന്തുകൊണ്ടാണ് മൈഗ്രേഷൻ പിഴച്ചത്
ഓപ്ഷണൽ പാരാമീറ്റർ ചേർത്ത മൈഗ്രേഷൻ വെറുതെ CREATE OR REPLACE FUNCTION എന്ന കമാൻഡ് പ്രവർത്തിപ്പിച്ചു. ഒരു റോളബാക്കിന് ശേഷമോ അല്ലെങ്കിൽ വീണ്ടും ഡിപ്ലോയ്മെന്റ് നടക്കുമ്പോഴോ മൈഗ്രേഷൻ രണ്ടാമത് പ്രവർത്തിച്ചപ്പോൾ, ഡാറ്റാബേസ് അതിനെ “നിലവിലുള്ളത് റീപ്ലേസ് ചെയ്യുക” എന്നതിന് പകരം “ഒരു പുതിയ ഓവർലോഡ് ചേർക്കുക” എന്നായാണ് കണക്കാക്കിയത്. മൈഗ്രേഷൻ ഫലമായി ഉണ്ടായ അവസ്ഥ പരിശോധിക്കാത്തതിനാൽ, ആ ഡ്യൂപ്ലിക്കേറ്റ് ശ്രദ്ധിക്കപ്പെടാതെ അവിടെത്തന്നെ തുടർന്നു.
റെപ്പോസിറ്ററി പരിശോധിച്ച സ്ക്രിപ്റ്റ് സോഴ്സ് ഫയലുകളാണ് പരിശോധിച്ചത്, ലൈവ് സ്കീമയല്ല. ബഗ് പിന്നിലൂടെ കടന്നുവന്നപ്പോൾ സ്ക്രിപ്റ്റ് മുൻവാതിലിലേക്കാണ് നോക്കിക്കൊണ്ടിരുന്നത്.
അപകടസാധ്യതകൾ
അവശ്യമായ ഒരു ഫങ്ക്ഷനിൽ ഉണ്ടാകുന്ന അവ്യക്തത ആ സർവീസിനെ മുഴുവൻ തകരാറിലാക്കാം. ഫങ്ക്ഷൻ എണ്ണം തെറ്റാണെങ്കിൽ ട്രാൻസാക്ഷൻ റോളബാക്ക് ചെയ്യുകയും സ്കീമ കാഷെ (schema cache) റീലോഡ് ചെയ്യാൻ അറിയിക്കുകയും ചെയ്യുക എന്നതായിരുന്നു പരിഹാരം.
മൈഗ്രേഷനുകൾ എങ്ങനെ സുരക്ഷിതമാക്കാം
ടീം മൈഗ്രേഷൻ കൂടുതൽ വ്യക്തമായ പരിശോധനകളോടെ പുനർനിർമ്മിച്ചു, അതിനെ ഒരു സ്വയം സാക്ഷ്യപ്പെടുത്തുന്ന (self-asserting) പ്രവർത്തനമാക്കി മാറ്റി:
- ഒരു ട്രാൻസാക്ഷൻ ആരംഭിക്കുക: അങ്ങനെ പരാജയപ്പെട്ടാൽ മാറ്റങ്ങൾ പൂർണ്ണമായും റോളബാക്ക് ചെയ്യാം.
- പഴയ ഫങ്ക്ഷൻ കൃത്യമായി ഡ്രോപ്പ് ചെയ്യുക: പുതിയ വേർഷൻ നിർമ്മിക്കുന്നതിന് മുമ്പ് പഴയ ഫങ്ക്ഷൻ ഡ്രോപ്പ് ചെയ്യുന്നത് ഒരു ഡെഫനിഷൻ മാത്രമേ നിലനിൽക്കുന്നുള്ളൂ എന്ന് ഉറപ്പാക്കുന്നു.
- പുതിയ ഫങ്ക്ഷൻ നിർമ്മിക്കുക: ആഗ്രഹിച്ച സിഗ്നേച്ചറോടെ പുതിയ ഫങ്ക്ഷൻ നിർമ്മിക്കുക.
- ഫങ്ക്ഷനുകളുടെ എണ്ണം പരിശോധിക്കുക:
pg_catalog-ൽ ആ പേരുള്ള ഫങ്ക്ഷനുകളുടെ എണ്ണം പരിശോധിക്കുകയും അത് കൃത്യം ഒന്ന് ആണെന്ന് ഉറപ്പുവരുത്തുകയും ചെയ്യുക. - റോളബാക്ക് ചെയ്യുക: എണ്ണത്തിൽ വ്യത്യാസമുണ്ടെങ്കിൽ ട്രാൻസാക്ഷൻ റോളബാക്ക് ചെയ്യുക, ഇത് ഡ്യൂപ്ലിക്കേറ്റ് നിലനിൽക്കുന്നത് തടയുന്നു.
- സ്കീമ കാഷെ റീലോഡ് ചെയ്യുക: സ്കീമ കാഷെ റീലോഡ് ചെയ്യാൻ അറിയിപ്പ് നൽകുക, അതുവഴി അടുത്ത ക്വറികൾ പുതിയ ഡെഫനിഷൻ കാണുന്നുണ്ടെന്ന് ഉറപ്പാക്കാം.
കോഡ് ശരിയാണെന്ന് കരുതുന്നതിന് പകരം ഡാറ്റാബേസിനോട് “എന്തൊക്കെ ഫങ്ക്ഷനുകൾ ഉണ്ട്?” എന്ന് ചോദിക്കുന്നതിലൂടെ, മൈഗ്രേഷൻ വീണ്ടും പ്രവർത്തിക്കുമ്പോഴോ, ഭാഗികമായ ഡിപ്ലോയ്മെന്റുകളിലോ അല്ലെങ്കിൽ മാനുവൽ എഡിറ്റിംഗിലോ കൂടുതൽ വിശ്വസനീയമാകുന്നു.
എതിർവാദം: സൗകര്യം vs സുരക്ഷ
CREATE OR REPLACE FUNCTION എന്നത് ഡെവലപ്പർമാർക്ക് പ്രത്യേക ഡ്രോപ്പ് സ്റ്റേറ്റ്മെന്റുകൾ എഴുതാതെ തന്നെ വേഗത്തിൽ മാറ്റങ്ങൾ വരുത്താൻ സഹായിക്കുന്നതിനാൽ ആകർഷകമാണ്. മൈഗ്രേഷനുകൾ ഒരിക്കൽ മാത്രം പ്രവർത്തിക്കുന്ന സാഹചര്യങ്ങളിൽ ഈ രീതി നന്നായി പ്രവർത്തിക്കും. എന്നാൽ ടെസ്റ്റ് ഡാറ്റാബേസുകൾ റീസെറ്റ് ചെയ്യുന്ന CI പൈപ്പ്ലൈനുകൾ, ഓട്ടോമേറ്റഡ് റോളബാക്കുകൾ അല്ലെങ്കിൽ പ്രൊഡക്ഷനിൽ മാനുവൽ റീ-അപ്ലിക്കേഷനുകൾ എന്നിവ കാരണം മൈഗ്രേഷനുകൾ വീണ്ടും പ്രവർത്തിപ്പിക്കേണ്ടി വരുമ്പോഴാണ് അപകടസാധ്യത ഉണ്ടാകുന്നത്.
പാഠം
CREATE OR REPLACE ഉപയോഗിച്ച് ഒരു ഫങ്ക്ഷന്റെ സിഗ്നേച്ചർ മാറ്റുന്നത് അത് റീപ്ലേസ് ചെയ്യപ്പെടുമെന്ന് ഉറപ്പുനൽകുന്നില്ല—ആർഗ്യുമെന്റ് ലിസ്റ്റിൽ വ്യത്യാസമുണ്ടെങ്കിൽ PostgreSQL നിശബ്ദമായി ഒരു ഓവർലോഡ് സൃഷ്ടിക്കും. മൈഗ്രേഷനുകളെ ആശ്രയിക്കുന്ന പ്രൊഡക്ഷൻ എൻവയോൺമെന്റുകൾ സോഴ്സ് കോഡ് മാത്രമല്ല, ഫലമായി ലഭിക്കുന്ന സ്കീമും പരിശോധിക്കണം. വ്യക്തമായ ഡ്രോപ്പ് കമാൻഡുകൾ, ട്രാൻസാക്ഷണൽ ചെക്കുകൾ, മൈഗ്രേഷന് ശേഷമുള്ള പരിശോധനകൾ എന്നിവ ഉൾപ്പെടുത്തുന്നത് ഒരു ലളിതമായ രീതിയെ വിശ്വസനീയവും ആവർത്തിക്കാവുന്നതുമായ ഒരു പ്രക്രിയയാക്കി മാറ്റുന്നു.
