പൈത്തൺ SQLAlchemy സെഷൻ മാനേജ്മെന്റിനെക്കുറിച്ചുള്ള സമഗ്രമായ വഴികാട്ടി. ഡാറ്റാ സമഗ്രതയും സ്ഥിരതയും ഉറപ്പാക്കാൻ ശക്തമായ ട്രാൻസാക്ഷൻ വിദ്യകളിൽ ശ്രദ്ധ കേന്ദ്രീകരിക്കുന്നു.
പൈത്തൺ SQLAlchemy സെഷൻ മാനേജ്മെന്റ്: ഡാറ്റാ സമഗ്രതയ്ക്കായി ട്രാൻസാക്ഷൻ കൈകാര്യം ചെയ്യുന്നത് പഠിക്കാം
SQLAlchemy എന്നത് ഡാറ്റാബേസുകളുമായി സംവദിക്കാൻ ഒരു സമഗ്ര ടൂൾകിറ്റ് നൽകുന്ന ശക്തവും വഴക്കമുള്ളതുമായ ഒരു പൈത്തൺ ലൈബ്രറിയാണ്. SQLAlchemy-യുടെ കാതൽ സെഷൻ എന്ന ആശയമാണ്, ഇത് നിങ്ങളുടെ ഡാറ്റാബേസിൽ നടത്തുന്ന എല്ലാ പ്രവർത്തനങ്ങൾക്കുമുള്ള ഒരു സ്റ്റേജിംഗ് സോണായി പ്രവർത്തിക്കുന്നു. ഡാറ്റാ സമഗ്രത നിലനിർത്തുന്നതിനും സ്ഥിരമായ ഡാറ്റാബേസ് സ്വഭാവം ഉറപ്പാക്കുന്നതിനും ശരിയായ സെഷൻ, ട്രാൻസാക്ഷൻ മാനേജ്മെന്റ് നിർണായകമാണ്, പ്രത്യേകിച്ചും ഒരേസമയം വരുന്ന അഭ്യർത്ഥനകൾ കൈകാര്യം ചെയ്യുന്ന സങ്കീർണ്ണ ആപ്ലിക്കേഷനുകളിൽ.
SQLAlchemy സെഷനുകൾ മനസ്സിലാക്കുന്നു
ഒരു SQLAlchemy സെഷൻ ഒരു യൂണിറ്റ് വർക്കിനെ, അതായത് ഡാറ്റാബേസുമായുള്ള ഒരു സംഭാഷണത്തെ പ്രതിനിധീകരിക്കുന്നു. ഇത് ഒബ്ജക്റ്റുകളിൽ വരുത്തിയ മാറ്റങ്ങൾ ട്രാക്ക് ചെയ്യുകയും, ഒരു ഒറ്റ അറ്റോമിക് പ്രവർത്തനമായി അവയെ ഡാറ്റാബേസിലേക്ക് നിലനിർത്താൻ നിങ്ങളെ അനുവദിക്കുകയും ചെയ്യുന്നു. ഇത് ഔദ്യോഗികമായി സംരക്ഷിക്കുന്നതിന് മുമ്പ് ഡാറ്റയിൽ മാറ്റങ്ങൾ വരുത്തുന്ന ഒരു വർക്ക്സ്പെയ്സായി ഇതിനെ കണക്കാക്കുക. ശരിയായി കൈകാര്യം ചെയ്യാത്ത ഒരു സെഷൻ ഡാറ്റയിലെ പൊരുത്തക്കേടുകൾക്കും കേടുപാടുകൾക്കും കാരണമായേക്കാം.
ഒരു സെഷൻ സൃഷ്ടിക്കുന്നു
നിങ്ങളുടെ ഡാറ്റാബേസുമായി സംവദിക്കാൻ തുടങ്ങുന്നതിന് മുമ്പ്, നിങ്ങൾ ഒരു സെഷൻ സൃഷ്ടിക്കേണ്ടതുണ്ട്. ഇതിന് SQLAlchemy-യുടെ എഞ്ചിൻ ഉപയോഗിച്ച് ആദ്യം ഡാറ്റാബേസിലേക്ക് ഒരു കണക്ഷൻ സ്ഥാപിക്കേണ്ടതുണ്ട്.
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
# Database connection string
db_url = 'sqlite:///:memory:' # Replace with your database URL (e.g., PostgreSQL, MySQL)
# Create an engine
engine = create_engine(db_url, echo=False) # echo=True to see the generated SQL
# Define a base for declarative models
Base = declarative_base()
# Define a simple model
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
email = Column(String)
def __repr__(self):
return f"<User(name='{self.name}', email='{self.email}')>"
# Create the table in the database
Base.metadata.create_all(engine)
# Create a session class
Session = sessionmaker(bind=engine)
# Instantiate a session
session = Session()
ഈ ഉദാഹരണത്തിൽ:
- ആവശ്യമായ SQLAlchemy മൊഡ്യൂളുകൾ നമ്മൾ ഇറക്കുമതി ചെയ്യുന്നു.
- ഒരു ഡാറ്റാബേസ് കണക്ഷൻ സ്ട്രിംഗ് (`db_url`) നിർവചിക്കുന്നു. ഈ ഉദാഹരണം ലാളിത്യത്തിനായി ഒരു ഇൻ-മെമ്മറി SQLite ഡാറ്റാബേസ് ഉപയോഗിക്കുന്നു, എന്നാൽ നിങ്ങൾ ഇത് നിങ്ങളുടെ ഡാറ്റാബേസ് സിസ്റ്റത്തിന് അനുയോജ്യമായ ഒരു കണക്ഷൻ സ്ട്രിംഗ് ഉപയോഗിച്ച് മാറ്റിസ്ഥാപിക്കേണ്ടതാണ് (ഉദാഹരണത്തിന്, PostgreSQL, MySQL). നിങ്ങൾ ഉപയോഗിക്കുന്ന ഡാറ്റാബേസ് എഞ്ചിനും ഡ്രൈവറും അനുസരിച്ച് നിർദ്ദിഷ്ട ഫോർമാറ്റ് വ്യത്യാസപ്പെടാം. ശരിയായ കണക്ഷൻ സ്ട്രിംഗ് ഫോർമാറ്റിനായി SQLAlchemy ഡോക്യുമെന്റേഷനും നിങ്ങളുടെ ഡാറ്റാബേസ് പ്രൊവൈഡറുടെ ഡോക്യുമെന്റേഷനും പരിശോധിക്കുക.
- `create_engine()` ഉപയോഗിച്ച് നമ്മൾ ഒരു `engine` സൃഷ്ടിക്കുന്നു. കണക്ഷൻ പൂൾ കൈകാര്യം ചെയ്യുന്നതിനും ഡാറ്റാബേസുമായുള്ള ആശയവിനിമയം നടത്തുന്നതിനും എഞ്ചിനാണ് ഉത്തരവാദി. `echo=True` പാരാമീറ്റർ ഡീബഗ്ഗിംഗിന് സഹായകമാണ്, കാരണം ഇത് ജനറേറ്റ് ചെയ്ത SQL സ്റ്റേറ്റ്മെന്റുകൾ കൺസോളിൽ പ്രിന്റ് ചെയ്യും.
- `declarative_base()` ഉപയോഗിച്ച് നമ്മൾ ഒരു അടിസ്ഥാന ക്ലാസ് (`Base`) നിർവചിക്കുന്നു. ഇത് നമ്മുടെ എല്ലാ SQLAlchemy മോഡലുകൾക്കും അടിസ്ഥാന ക്ലാസായി ഉപയോഗിക്കുന്നു.
- `users` എന്ന് പേരുള്ള ഒരു ഡാറ്റാബേസ് ടേബിളിലേക്ക് മാപ്പ് ചെയ്ത ഒരു `User` മോഡൽ നമ്മൾ നിർവചിക്കുന്നു.
- `Base.metadata.create_all(engine)` ഉപയോഗിച്ച് നമ്മൾ ഡാറ്റാബേസിൽ ടേബിൾ സൃഷ്ടിക്കുന്നു.
- `sessionmaker(bind=engine)` ഉപയോഗിച്ച് നമ്മൾ ഒരു സെഷൻ ക്ലാസ് സൃഷ്ടിക്കുന്നു. ഇത് നിർദ്ദിഷ്ട എഞ്ചിൻ ഉപയോഗിക്കാൻ സെഷൻ ക്ലാസ് ക്രമീകരിക്കുന്നു.
- അവസാനമായി, `Session()` ഉപയോഗിച്ച് നമ്മൾ ഒരു സെഷൻ ഇൻസ്റ്റൻഷ്യേറ്റ് ചെയ്യുന്നു.
ട്രാൻസാക്ഷനുകൾ മനസ്സിലാക്കുന്നു
ഒരു ട്രാൻസാക്ഷൻ എന്നത് ഒരു ഒറ്റ ലോജിക്കൽ യൂണിറ്റ് വർക്കായി കണക്കാക്കുന്ന ഡാറ്റാബേസ് പ്രവർത്തനങ്ങളുടെ ഒരു ശ്രേണിയാണ്. ട്രാൻസാക്ഷനുകൾ ACID പ്രോപ്പർട്ടികൾ പാലിക്കുന്നു:
- അറ്റോമിസിറ്റി: ട്രാൻസാക്ഷനിലെ എല്ലാ പ്രവർത്തനങ്ങളും പൂർണ്ണമായി വിജയിക്കുകയോ പൂർണ്ണമായി പരാജയപ്പെടുകയോ ചെയ്യും. ട്രാൻസാക്ഷന്റെ ഏതെങ്കിലും ഭാഗം പരാജയപ്പെട്ടാൽ, മുഴുവൻ ട്രാൻസാക്ഷനും റോൾബാക്ക് ചെയ്യപ്പെടും.
- കൺസിസ്റ്റൻസി: ട്രാൻസാക്ഷൻ ഡാറ്റാബേസിനെ ഒരു സാധുവായ അവസ്ഥയിൽ നിലനിർത്തണം. ഇതിന് ഡാറ്റാബേസ് നിയന്ത്രണങ്ങളോ നിയമങ്ങളോ ലംഘിക്കാൻ കഴിയില്ല.
- ഐസൊലേഷൻ: ഒരേസമയം നടക്കുന്ന ട്രാൻസാക്ഷനുകൾ പരസ്പരം വേർതിരിക്കപ്പെട്ടിരിക്കുന്നു. ഒരു ട്രാൻസാക്ഷൻ വരുത്തുന്ന മാറ്റങ്ങൾ ആദ്യ ട്രാൻസാക്ഷൻ കമ്മിറ്റ് ചെയ്യുന്നത് വരെ മറ്റ് ട്രാൻസാക്ഷനുകൾക്ക് ദൃശ്യമാകില്ല.
- ഡ്യൂറബിലിറ്റി: ഒരു ട്രാൻസാക്ഷൻ കമ്മിറ്റ് ചെയ്തുകഴിഞ്ഞാൽ, അതിലെ മാറ്റങ്ങൾ സ്ഥിരമാണ്, സിസ്റ്റം തകരാറുകൾ ഉണ്ടായാലും നിലനിൽക്കും.
ഈ ACID പ്രോപ്പർട്ടികൾ നിലനിർത്തുന്നുവെന്ന് ഉറപ്പാക്കാൻ SQLAlchemy ട്രാൻസാക്ഷനുകൾ കൈകാര്യം ചെയ്യാനുള്ള സംവിധാനങ്ങൾ നൽകുന്നു.
അടിസ്ഥാന ട്രാൻസാക്ഷൻ കൈകാര്യം ചെയ്യൽ
ഏറ്റവും സാധാരണമായ ട്രാൻസാക്ഷൻ പ്രവർത്തനങ്ങൾ കമ്മിറ്റ്, റോൾബാക്ക് എന്നിവയാണ്.
ട്രാൻസാക്ഷനുകൾ കമ്മിറ്റ് ചെയ്യുന്നു
ഒരു ട്രാൻസാക്ഷനിലെ എല്ലാ പ്രവർത്തനങ്ങളും വിജയകരമായി പൂർത്തിയാകുമ്പോൾ, നിങ്ങൾ ട്രാൻസാക്ഷൻ കമ്മിറ്റ് ചെയ്യുന്നു. ഇത് മാറ്റങ്ങൾ ഡാറ്റാബേസിലേക്ക് നിലനിർത്തുന്നു.
try:
# Add a new user
new_user = User(name='Alice Smith', email='alice.smith@example.com')
session.add(new_user)
# Commit the transaction
session.commit()
print("Transaction committed successfully!")
except Exception as e:
# Handle exceptions
print(f"An error occurred: {e}")
session.rollback()
print("Transaction rolled back.")
finally:
session.close()
ഈ ഉദാഹരണത്തിൽ:
- നമ്മൾ ഒരു പുതിയ `User` ഒബ്ജക്റ്റ് സെഷനിലേക്ക് ചേർക്കുന്നു.
- മാറ്റങ്ങൾ ഡാറ്റാബേസിലേക്ക് നിലനിർത്താൻ നമ്മൾ `session.commit()` എന്ന് വിളിക്കുന്നു.
- സംഭവിക്കാനിടയുള്ള എക്സപ്ഷനുകൾ കൈകാര്യം ചെയ്യാൻ നമ്മൾ കോഡിനെ ഒരു `try...except...finally` ബ്ലോക്കിൽ പൊതിയുന്നു.
- ഒരു എക്സപ്ഷൻ ഉണ്ടായാൽ, ട്രാൻസാക്ഷനിൽ വരുത്തിയ മാറ്റങ്ങൾ പഴയപടിയാക്കാൻ നമ്മൾ `session.rollback()` എന്ന് വിളിക്കുന്നു.
- സെഷൻ റിലീസ് ചെയ്യാനും കണക്ഷൻ പൂളിലേക്ക് കണക്ഷൻ തിരികെ നൽകാനും നമ്മൾ എപ്പോഴും `finally` ബ്ലോക്കിൽ `session.close()` എന്ന് വിളിക്കുന്നു. റിസോഴ്സ് ചോർച്ച ഒഴിവാക്കുന്നതിന് ഇത് നിർണായകമാണ്. സെഷനുകൾ ക്ലോസ് ചെയ്യാതിരിക്കുന്നത് കണക്ഷൻ തീർന്നുപോകുന്നതിനും ആപ്ലിക്കേഷൻ അസ്ഥിരതയ്ക്കും കാരണമാകും.
ട്രാൻസാക്ഷനുകൾ റോൾബാക്ക് ചെയ്യുന്നു
ഒരു ട്രാൻസാക്ഷൻ സമയത്ത് ഏതെങ്കിലും പിശക് സംഭവിക്കുകയാണെങ്കിൽ, അല്ലെങ്കിൽ മാറ്റങ്ങൾ നിലനിർത്തേണ്ടതില്ലെന്ന് നിങ്ങൾ തീരുമാനിക്കുകയാണെങ്കിൽ, നിങ്ങൾ ട്രാൻസാക്ഷൻ റോൾബാക്ക് ചെയ്യുന്നു. ഇത് ഡാറ്റാബേസിനെ ട്രാൻസാക്ഷൻ ആരംഭിക്കുന്നതിന് മുമ്പുള്ള അവസ്ഥയിലേക്ക് തിരികെ കൊണ്ടുവരുന്നു.
try:
# Add a user with an invalid email (example to force a rollback)
invalid_user = User(name='Bob Johnson', email='invalid-email')
session.add(invalid_user)
# The commit will fail if the email is not validated on the database level
session.commit()
print("Transaction committed.")
except Exception as e:
print(f"An error occurred: {e}")
session.rollback()
print("Transaction rolled back successfully.")
finally:
session.close()
ഈ ഉദാഹരണത്തിൽ, `invalid_user` ചേർക്കുന്നത് ഒരു എക്സപ്ഷൻ (ഉദാഹരണത്തിന്, ഒരു ഡാറ്റാബേസ് നിയന്ത്രണ ലംഘനം കാരണം) ഉയർത്തുകയാണെങ്കിൽ, `session.rollback()` കോൾ ചേർക്കാൻ ശ്രമിച്ചതിനെ പഴയപടിയാക്കുകയും ഡാറ്റാബേസിൽ മാറ്റമില്ലാതെ തുടരുകയും ചെയ്യും.
വിപുലമായ ട്രാൻസാക്ഷൻ മാനേജ്മെന്റ്
ട്രാൻസാക്ഷൻ സ്കോപ്പിംഗിനായി `with` സ്റ്റേറ്റ്മെന്റ് ഉപയോഗിക്കുന്നു
`with` സ്റ്റേറ്റ്മെന്റ് ഉപയോഗിക്കുന്നത് ട്രാൻസാക്ഷനുകൾ കൈകാര്യം ചെയ്യാനുള്ള കൂടുതൽ പൈത്തോണിക് (Pythonic) ആയതും ശക്തവുമായ ഒരു മാർഗ്ഗമാണ്. എക്സപ്ഷനുകൾ ഉണ്ടായാലും സെഷൻ ശരിയായി ക്ലോസ് ചെയ്യപ്പെടുന്നുവെന്ന് ഇത് ഉറപ്പാക്കുന്നു.
from contextlib import contextmanager
@contextmanager
def session_scope():
"""Provide a transactional scope around a series of operations."""
session = Session()
try:
yield session
session.commit()
except Exception:
session.rollback()
raise
finally:
session.close()
# Usage:
with session_scope() as session:
new_user = User(name='Charlie Brown', email='charlie.brown@example.com')
session.add(new_user)
# Operations within the 'with' block
# If no exceptions occur, the transaction is committed automatically.
# If an exception occurs, the transaction is rolled back automatically.
print("User added.")
print("Transaction completed (committed or rolled back).")
`session_scope` ഫംഗ്ഷൻ ഒരു കോൺടെക്സ്റ്റ് മാനേജർ ആണ്. നിങ്ങൾ `with` ബ്ലോക്കിൽ പ്രവേശിക്കുമ്പോൾ, ഒരു പുതിയ സെഷൻ സൃഷ്ടിക്കപ്പെടുന്നു. നിങ്ങൾ `with` ബ്ലോക്കിൽ നിന്ന് പുറത്തുകടക്കുമ്പോൾ, സെഷൻ ഒന്നുകിൽ കമ്മിറ്റ് ചെയ്യപ്പെടുന്നു (എക്സപ്ഷനുകൾ ഒന്നും സംഭവിച്ചില്ലെങ്കിൽ) അല്ലെങ്കിൽ റോൾബാക്ക് ചെയ്യപ്പെടുന്നു (ഒരു എക്സപ്ഷൻ സംഭവിച്ചാൽ). സെഷൻ എപ്പോഴും `finally` ബ്ലോക്കിൽ ക്ലോസ് ചെയ്യപ്പെടും.
നെസ്റ്റഡ് ട്രാൻസാക്ഷനുകൾ (സേവ്പോയിന്റുകൾ)
SQLAlchemy സേവ്പോയിന്റുകൾ ഉപയോഗിച്ച് നെസ്റ്റഡ് ട്രാൻസാക്ഷനുകളെ പിന്തുണയ്ക്കുന്നു. ഒരു വലിയ ട്രാൻസാക്ഷനുള്ളിൽ ഒരു നിർദ്ദിഷ്ട പോയിന്റിലേക്ക് റോൾബാക്ക് ചെയ്യാൻ ഒരു സേവ്പോയിന്റ് നിങ്ങളെ അനുവദിക്കുന്നു, മുഴുവൻ ട്രാൻസാക്ഷനെയും ബാധിക്കാതെ.
try:
with session_scope() as session:
user1 = User(name='David Lee', email='david.lee@example.com')
session.add(user1)
session.flush() # Send changes to the database but don't commit yet
# Create a savepoint
savepoint = session.begin_nested()
try:
user2 = User(name='Eve Wilson', email='eve.wilson@example.com')
session.add(user2)
session.flush()
# Simulate an error
raise ValueError("Simulated error during nested transaction")
except Exception as e:
print(f"Nested transaction error: {e}")
savepoint.rollback()
print("Nested transaction rolled back to savepoint.")
# Continue with the outer transaction, user1 will still be added
user3 = User(name='Frank Miller', email='frank.miller@example.com')
session.add(user3)
except Exception as e:
print(f"Outer transaction error: {e}")
#Commit will commit user1 and user3, but not user2 due to the nested rollback
try:
with session_scope() as session:
#Verify only user1 and user3 exist
users = session.query(User).all()
for user in users:
print(user)
except Exception as e:
print(f"Unexpected Exception: {e}") #Should not happen
ഈ ഉദാഹരണത്തിൽ:
- `session_scope()` ഉപയോഗിച്ച് നമ്മൾ ഒരു ഔട്ടർ ട്രാൻസാക്ഷൻ ആരംഭിക്കുന്നു.
- `user1` നെ സെഷനിലേക്ക് ചേർക്കുകയും മാറ്റങ്ങൾ ഡാറ്റാബേസിലേക്ക് ഫ്ലഷ് ചെയ്യുകയും ചെയ്യുന്നു. `flush()` മാറ്റങ്ങൾ ഡാറ്റാബേസ് സെർവറിലേക്ക് അയയ്ക്കുന്നു, പക്ഷേ അവ കമ്മിറ്റ് ചെയ്യുന്നില്ല. മുഴുവൻ ട്രാൻസാക്ഷനും കമ്മിറ്റ് ചെയ്യുന്നതിന് മുമ്പ് മാറ്റങ്ങൾ സാധുവാണോ എന്ന് (ഉദാഹരണത്തിന്, നിയന്ത്രണ ലംഘനങ്ങൾ ഇല്ല) പരിശോധിക്കാൻ ഇത് നിങ്ങളെ അനുവദിക്കുന്നു.
- `session.begin_nested()` ഉപയോഗിച്ച് നമ്മൾ ഒരു സേവ്പോയിന്റ് സൃഷ്ടിക്കുന്നു.
- നെസ്റ്റഡ് ട്രാൻസാക്ഷനിൽ, നമ്മൾ `user2` ചേർക്കുകയും ഒരു പിശക് അനുകരിക്കുകയും ചെയ്യുന്നു.
- `savepoint.rollback()` ഉപയോഗിച്ച് നമ്മൾ നെസ്റ്റഡ് ട്രാൻസാക്ഷൻ സേവ്പോയിന്റിലേക്ക് റോൾബാക്ക് ചെയ്യുന്നു. ഇത് നെസ്റ്റഡ് ട്രാൻസാക്ഷനിൽ വരുത്തിയ മാറ്റങ്ങൾ (അതായത്, `user2` നെ ചേർത്തത്) മാത്രം പഴയപടിയാക്കുന്നു.
- നമ്മൾ ഔട്ടർ ട്രാൻസാക്ഷനുമായി തുടരുകയും `user3` ചേർക്കുകയും ചെയ്യുന്നു.
- ഔട്ടർ ട്രാൻസാക്ഷൻ കമ്മിറ്റ് ചെയ്യപ്പെടുന്നു, `user1`, `user3` എന്നിവ ഡാറ്റാബേസിലേക്ക് നിലനിർത്തുന്നു, അതേസമയം `user2` സേവ്പോയിന്റ് റോൾബാക്ക് കാരണം ഉപേക്ഷിക്കപ്പെടുന്നു.
ഐസൊലേഷൻ ലെവലുകൾ നിയന്ത്രിക്കുന്നു
ഐസൊലേഷൻ ലെവലുകൾ ഒരേസമയം നടക്കുന്ന ട്രാൻസാക്ഷനുകൾ പരസ്പരം എത്രത്തോളം വേർതിരിക്കപ്പെട്ടിരിക്കുന്നു എന്ന് നിർവചിക്കുന്നു. ഉയർന്ന ഐസൊലേഷൻ ലെവലുകൾ കൂടുതൽ ഡാറ്റാ സ്ഥിരത നൽകുന്നു, പക്ഷേ കൺകറൻസിയും പ്രകടനവും കുറയ്ക്കാൻ സാധ്യതയുണ്ട്. നിങ്ങളുടെ ട്രാൻസാക്ഷനുകളുടെ ഐസൊലേഷൻ ലെവൽ നിയന്ത്രിക്കാൻ SQLAlchemy നിങ്ങളെ അനുവദിക്കുന്നു.
സാധാരണ ഐസൊലേഷൻ ലെവലുകൾ ഇവയാണ്:
- Read Uncommitted: ഏറ്റവും താഴ്ന്ന ഐസൊലേഷൻ ലെവൽ. ട്രാൻസാക്ഷനുകൾക്ക് മറ്റ് ട്രാൻസാക്ഷനുകൾ വരുത്തിയ കമ്മിറ്റ് ചെയ്യാത്ത മാറ്റങ്ങൾ കാണാൻ കഴിയും. ഇത് ഡേർട്ടി റീഡുകൾക്ക് കാരണമായേക്കാം.
- Read Committed: ട്രാൻസാക്ഷനുകൾക്ക് മറ്റ് ട്രാൻസാക്ഷനുകൾ വരുത്തിയ കമ്മിറ്റ് ചെയ്ത മാറ്റങ്ങൾ മാത്രമേ കാണാൻ കഴിയൂ. ഇത് ഡേർട്ടി റീഡുകൾ തടയുന്നു, പക്ഷേ നോൺ-റിപ്പീറ്റബിൾ റീഡുകൾക്കും ഫാന്റം റീഡുകൾക്കും കാരണമായേക്കാം.
- Repeatable Read: ട്രാൻസാക്ഷനുകൾക്ക് മുഴുവൻ ട്രാൻസാക്ഷൻ സമയത്തും ഒരേ ഡാറ്റ കാണാൻ കഴിയും, മറ്റ് ട്രാൻസാക്ഷനുകൾ അത് മാറ്റിയെഴുതിയാൽ പോലും. ഇത് ഡേർട്ടി റീഡുകളും നോൺ-റിപ്പീറ്റബിൾ റീഡുകളും തടയുന്നു, പക്ഷേ ഫാന്റം റീഡുകൾക്ക് കാരണമായേക്കാം.
- Serializable: ഏറ്റവും ഉയർന്ന ഐസൊലേഷൻ ലെവൽ. ട്രാൻസാക്ഷനുകൾ പരസ്പരം പൂർണ്ണമായി വേർതിരിക്കപ്പെട്ടിരിക്കുന്നു. ഇത് ഡേർട്ടി റീഡുകൾ, നോൺ-റിപ്പീറ്റബിൾ റീഡുകൾ, ഫാന്റം റീഡുകൾ എന്നിവ തടയുന്നു, പക്ഷേ കൺകറൻസി ഗണ്യമായി കുറയ്ക്കാൻ സാധ്യതയുണ്ട്.
സ്ഥിരമായ ഐസൊലേഷൻ ലെവൽ ഡാറ്റാബേസ് സിസ്റ്റത്തെ ആശ്രയിച്ചിരിക്കും. എഞ്ചിൻ സൃഷ്ടിക്കുമ്പോൾ അല്ലെങ്കിൽ ഒരു ട്രാൻസാക്ഷൻ ആരംഭിക്കുമ്പോൾ നിങ്ങൾക്ക് ഐസൊലേഷൻ ലെവൽ സജ്ജമാക്കാൻ കഴിയും.
ഉദാഹരണം (PostgreSQL):
from sqlalchemy.dialects.postgresql import dialect
# Set isolation level when creating the engine
engine = create_engine('postgresql://user:password@host:port/database',
connect_args={'options': '-c statement_timeout=1000'} #Example of timeout
)
# Set the isolation level when beginning a transaction (database specific)
# For postgresql, it's recommended to set it on the connection, not engine.
from sqlalchemy import event
from sqlalchemy.pool import Pool
@event.listens_for(Pool, "connect")
def set_isolation_level(dbapi_connection, connection_record):
existing_autocommit = dbapi_connection.autocommit
dbapi_connection.autocommit = True
cursor = dbapi_connection.cursor()
cursor.execute("SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE")
dbapi_connection.autocommit = existing_autocommit
cursor.close()
# Then transactions created via SQLAlchemy will use the configured isolation level.
പ്രധാനം: ഐസൊലേഷൻ ലെവലുകൾ സജ്ജീകരിക്കുന്ന രീതി ഡാറ്റാബേസ്-നിർദ്ദിഷ്ടമാണ്. ശരിയായ സിന്റാക്സിനായി നിങ്ങളുടെ ഡാറ്റാബേസ് ഡോക്യുമെന്റേഷൻ പരിശോധിക്കുക. ഐസൊലേഷൻ ലെവലുകൾ തെറ്റായി സജ്ജീകരിക്കുന്നത് അപ്രതീക്ഷിത സ്വഭാവത്തിലേക്കോ പിശകുകളിലേക്കോ നയിച്ചേക്കാം.
കൺകറൻസി കൈകാര്യം ചെയ്യുന്നു
ഒരേ സമയം ഒന്നിലധികം ഉപയോക്താക്കളോ പ്രോസസ്സുകളോ ഒരേ ഡാറ്റ ആക്സസ് ചെയ്യുമ്പോൾ, ഡാറ്റാ കേടുപാടുകൾ തടയുന്നതിനും ഡാറ്റാ സ്ഥിരത ഉറപ്പാക്കുന്നതിനും കൺകറൻസി ശരിയായി കൈകാര്യം ചെയ്യേണ്ടത് നിർണായകമാണ്. ഒപ്റ്റിമിസ്റ്റിക് ലോക്കിംഗ്, പെസിമിസ്റ്റിക് ലോക്കിംഗ് എന്നിവയുൾപ്പെടെ കൺകറൻസി കൈകാര്യം ചെയ്യാൻ SQLAlchemy നിരവധി സംവിധാനങ്ങൾ നൽകുന്നു.
ഒപ്റ്റിമിസ്റ്റിക് ലോക്കിംഗ്
ഒപ്റ്റിമിസ്റ്റിക് ലോക്കിംഗ് അനുമാനിക്കുന്നത് തർക്കങ്ങൾ വളരെ അപൂർവമാണെന്നാണ്. ഒരു ട്രാൻസാക്ഷൻ കമ്മിറ്റ് ചെയ്യുന്നതിന് മുമ്പ് മറ്റ് ട്രാൻസാക്ഷനുകൾ വരുത്തിയ മാറ്റങ്ങൾക്കായി ഇത് പരിശോധിക്കുന്നു. ഒരു തർക്കം കണ്ടെത്തിയാൽ, ട്രാൻസാക്ഷൻ റോൾബാക്ക് ചെയ്യപ്പെടുന്നു.
ഒപ്റ്റിമിസ്റ്റിക് ലോക്കിംഗ് നടപ്പിലാക്കാൻ, നിങ്ങൾ സാധാരണയായി നിങ്ങളുടെ ടേബിളിൽ ഒരു വേർഷൻ കോളം ചേർക്കുന്നു. ഈ കോളം റോ അപ്ഡേറ്റ് ചെയ്യുമ്പോഴെല്ലാം സ്വയമേവ വർദ്ധിപ്പിക്കപ്പെടുന്നു.
from sqlalchemy import Column, Integer, String, Integer
from sqlalchemy.orm import declarative_base
Base = declarative_base()
class Article(Base):
__tablename__ = 'articles'
id = Column(Integer, primary_key=True)
title = Column(String)
content = Column(String)
version = Column(Integer, nullable=False, default=1)
def __repr__(self):
return f"<Article(title='{self.title}', version='{self.version}')>"
#Inside of the try catch block
def update_article(session, article_id, new_content):
article = session.query(Article).filter_by(id=article_id).first()
if article is None:
raise ValueError("Article not found")
original_version = article.version
# Update the content and increment the version
article.content = new_content
article.version += 1
# Attempt to update, checking the version column in the WHERE clause
rows_affected = session.query(Article).filter(
Article.id == article_id,
Article.version == original_version
).update({
Article.content: new_content,
Article.version: article.version
}, synchronize_session=False)
if rows_affected == 0:
session.rollback()
raise ValueError("Conflict: Article has been updated by another transaction.")
session.commit()
ഈ ഉദാഹരണത്തിൽ:
- നമ്മൾ `Article` മോഡലിലേക്ക് ഒരു `version` കോളം ചേർക്കുന്നു.
- ആർട്ടിക്കിൾ അപ്ഡേറ്റ് ചെയ്യുന്നതിന് മുമ്പ്, നമ്മൾ നിലവിലെ വേർഷൻ നമ്പർ സംഭരിക്കുന്നു.
- `UPDATE` സ്റ്റേറ്റ്മെന്റിൽ, വേർഷൻ കോളം ഇപ്പോഴും സംഭരിച്ച വേർഷൻ നമ്പറിന് തുല്യമാണോ എന്ന് പരിശോധിക്കുന്ന ഒരു `WHERE` ക്ലോസ് നമ്മൾ ഉൾപ്പെടുത്തുന്നു. `synchronize_session=False` SQLAlchemy അപ്ഡേറ്റ് ചെയ്ത ഒബ്ജക്റ്റിനെ വീണ്ടും ലോഡ് ചെയ്യുന്നത് തടയുന്നു; നമ്മൾ വേർഷനിംഗ് വ്യക്തമായി കൈകാര്യം ചെയ്യുകയാണ്.
- വേർഷൻ കോളം മറ്റൊരു ട്രാൻസാക്ഷൻ വഴി മാറ്റിയെഴുതിയെങ്കിൽ, `UPDATE` സ്റ്റേറ്റ്മെന്റ് ഒരു റോയേയും ബാധിക്കില്ല (rows_affected 0 ആയിരിക്കും), നമ്മൾ ഒരു എക്സപ്ഷൻ ഉയർത്തുന്നു.
- നമ്മൾ ട്രാൻസാക്ഷൻ റോൾബാക്ക് ചെയ്യുകയും ഒരു തർക്കം സംഭവിച്ചുവെന്ന് ഉപയോക്താവിനെ അറിയിക്കുകയും ചെയ്യുന്നു.
പെസിമിസ്റ്റിക് ലോക്കിംഗ്
തർക്കങ്ങൾ ഉണ്ടാകാൻ സാധ്യതയുണ്ടെന്ന് പെസിമിസ്റ്റിക് ലോക്കിംഗ് അനുമാനിക്കുന്നു. ഒരു റോയിലോ ടേബിളിലോ മാറ്റങ്ങൾ വരുത്തുന്നതിന് മുമ്പ് അത് ഒരു ലോക്ക് നേടുന്നു. ലോക്ക് റിലീസ് ചെയ്യുന്നത് വരെ മറ്റ് ട്രാൻസാക്ഷനുകൾ ഡാറ്റയിൽ മാറ്റങ്ങൾ വരുത്തുന്നത് ഇത് തടയുന്നു.
`with_for_update()` പോലുള്ള ലോക്കുകൾ നേടുന്നതിനുള്ള നിരവധി ഫംഗ്ഷനുകൾ SQLAlchemy നൽകുന്നു.
# Example using PostgreSQL
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker, declarative_base
# Database setup (replace with your actual database URL)
db_url = 'postgresql://user:password@host:port/database'
engine = create_engine(db_url, echo=False) #Set echo to true if you would like to see the SQL generated
Base = declarative_base()
class Item(Base):
__tablename__ = 'items'
id = Column(Integer, primary_key=True)
name = Column(String)
value = Column(Integer)
def __repr__(self):
return f"<Item(name='{self.name}', value='{self.value}')>"
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
#Function to update the item (within a try/except)
def update_item_value(session, item_id, new_value):
# Acquire a pessimistic lock on the item
item = session.query(Item).filter(Item.id == item_id).with_for_update().first()
if item is None:
raise ValueError("Item not found")
# Update the item's value
item.value = new_value
session.commit()
return True
ഈ ഉദാഹരണത്തിൽ:
- `Item` റോ അപ്ഡേറ്റ് ചെയ്യുന്നതിന് മുമ്പ് അതിൽ ഒരു ലോക്ക് നേടാൻ നമ്മൾ `with_for_update()` ഉപയോഗിക്കുന്നു. നിലവിലെ ട്രാൻസാക്ഷൻ കമ്മിറ്റ് ചെയ്യുകയോ റോൾബാക്ക് ചെയ്യുകയോ ചെയ്യുന്നത് വരെ മറ്റ് ട്രാൻസാക്ഷനുകൾ റോയിൽ മാറ്റങ്ങൾ വരുത്തുന്നത് ഇത് തടയുന്നു. `with_for_update()` ഫംഗ്ഷൻ ഡാറ്റാബേസ്-നിർദ്ദിഷ്ടമാണ്; കൂടുതൽ വിവരങ്ങൾക്കായി നിങ്ങളുടെ ഡാറ്റാബേസ് ഡോക്യുമെന്റേഷൻ പരിശോധിക്കുക. ചില ഡാറ്റാബേസുകൾക്ക് വ്യത്യസ്ത ലോക്കിംഗ് സംവിധാനങ്ങളോ സിന്റാക്സുകളോ ഉണ്ടാകാം.
പ്രധാനം: പെസിമിസ്റ്റിക് ലോക്കിംഗ് കൺകറൻസിയും പ്രകടനവും കുറയ്ക്കാൻ സാധ്യതയുണ്ട്, അതിനാൽ അത് ആവശ്യമുള്ളപ്പോൾ മാത്രം ഉപയോഗിക്കുക.
എക്സപ്ഷൻ കൈകാര്യം ചെയ്യാനുള്ള മികച്ച രീതികൾ
ഡാറ്റാ സമഗ്രത ഉറപ്പാക്കുന്നതിനും ആപ്ലിക്കേഷൻ ക്രാഷുകൾ തടയുന്നതിനും ശരിയായ എക്സപ്ഷൻ കൈകാര്യം ചെയ്യൽ നിർണായകമാണ്. നിങ്ങളുടെ ഡാറ്റാബേസ് പ്രവർത്തനങ്ങൾ എപ്പോഴും `try...except` ബ്ലോക്കുകളിൽ പൊതിയുകയും എക്സപ്ഷനുകൾ ശരിയായി കൈകാര്യം ചെയ്യുകയും ചെയ്യുക.
എക്സപ്ഷൻ കൈകാര്യം ചെയ്യുന്നതിനുള്ള ചില മികച്ച രീതികൾ ഇതാ:
- നിർദ്ദിഷ്ട എക്സപ്ഷനുകൾ പിടിക്കുക: `Exception` പോലുള്ള പൊതുവായ എക്സപ്ഷനുകൾ പിടിക്കുന്നത് ഒഴിവാക്കുക. വ്യത്യസ്ത തരം പിശകുകൾ വ്യത്യസ്തമായി കൈകാര്യം ചെയ്യാൻ `sqlalchemy.exc.IntegrityError` അല്ലെങ്കിൽ `sqlalchemy.exc.OperationalError` പോലുള്ള നിർദ്ദിഷ്ട എക്സപ്ഷനുകൾ പിടിക്കുക.
- ട്രാൻസാക്ഷനുകൾ റോൾബാക്ക് ചെയ്യുക: ഒരു എക്സപ്ഷൻ ഉണ്ടായാൽ എപ്പോഴും ട്രാൻസാക്ഷൻ റോൾബാക്ക് ചെയ്യുക.
- എക്സപ്ഷനുകൾ ലോഗ് ചെയ്യുക: പ്രശ്നങ്ങൾ കണ്ടെത്താനും പരിഹരിക്കാനും സഹായിക്കുന്നതിന് എക്സപ്ഷനുകൾ ലോഗ് ചെയ്യുക. നിങ്ങളുടെ ലോഗുകളിൽ കഴിയുന്നത്രയും കോൺടെക്സ്റ്റ് ഉൾപ്പെടുത്തുക (ഉദാഹരണത്തിന്, ഉപയോക്തൃ ഐഡി, ഇൻപുട്ട് ഡാറ്റ, ടൈംസ്റ്റാമ്പ്).
- ഉചിതമെങ്കിൽ എക്സപ്ഷനുകൾ വീണ്ടും ഉയർത്തുക: നിങ്ങൾക്ക് ഒരു എക്സപ്ഷൻ കൈകാര്യം ചെയ്യാൻ കഴിയുന്നില്ലെങ്കിൽ, ഉയർന്ന തലത്തിലുള്ള ഒരു ഹാൻഡ്ലർക്ക് അത് കൈകാര്യം ചെയ്യാൻ അനുവദിക്കുന്നതിന് അത് വീണ്ടും ഉയർത്തുക.
- റിസോഴ്സുകൾ വൃത്തിയാക്കുക: എപ്പോഴും സെഷൻ ക്ലോസ് ചെയ്യുകയും മറ്റ് റിസോഴ്സുകൾ ഒരു `finally` ബ്ലോക്കിൽ റിലീസ് ചെയ്യുകയും ചെയ്യുക.
import logging
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker, declarative_base
from sqlalchemy.exc import IntegrityError, OperationalError
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# Database setup (replace with your actual database URL)
db_url = 'postgresql://user:password@host:port/database'
engine = create_engine(db_url, echo=False)
Base = declarative_base()
class Product(Base):
__tablename__ = 'products'
id = Column(Integer, primary_key=True)
name = Column(String)
price = Column(Integer)
def __repr__(self):
return f"<Product(name='{self.name}', price='{self.price}')>"
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
# Function to add a product
def add_product(session, name, price):
try:
new_product = Product(name=name, price=price)
session.add(new_product)
session.commit()
logging.info(f"Product '{name}' added successfully.")
return True
except IntegrityError as e:
session.rollback()
logging.error(f"IntegrityError: {e}")
#Handle database constraint violations (e.g., duplicate name)
return False
except OperationalError as e:
session.rollback()
logging.error(f"OperationalError: {e}")
#Handle connection errors or other operational issues
return False
except Exception as e:
session.rollback()
logging.exception(f"An unexpected error occurred: {e}")
# Handle any other unexpected errors
return False
finally:
session.close()
ഈ ഉദാഹരണത്തിൽ:
- പ്രോസസ്സ് സമയത്ത് ഇവന്റുകൾ രേഖപ്പെടുത്തുന്നതിന് നമ്മൾ ലോഗിംഗ് ക്രമീകരിക്കുന്നു.
- `IntegrityError` (നിയന്ത്രണ ലംഘനങ്ങൾക്ക്) `OperationalError` (കണക്ഷൻ പിശകുകൾക്ക്) പോലുള്ള നിർദ്ദിഷ്ട എക്സപ്ഷനുകൾ നമ്മൾ പിടിക്കുന്നു.
- `except` ബ്ലോക്കുകളിൽ നമ്മൾ ട്രാൻസാക്ഷൻ റോൾബാക്ക് ചെയ്യുന്നു.
- `logging` മൊഡ്യൂൾ ഉപയോഗിച്ച് നമ്മൾ എക്സപ്ഷനുകൾ ലോഗ് ചെയ്യുന്നു. `logging.exception()` രീതി ലോഗ് സന്ദേശത്തിൽ സ്റ്റാക്ക് ട്രെയ്സ് സ്വയമേവ ഉൾപ്പെടുത്തുന്നു.
- നമുക്ക് ഒരു എക്സപ്ഷൻ കൈകാര്യം ചെയ്യാൻ കഴിയുന്നില്ലെങ്കിൽ നമ്മൾ അത് വീണ്ടും ഉയർത്തുന്നു.
- `finally` ബ്ലോക്കിൽ നമ്മൾ സെഷൻ ക്ലോസ് ചെയ്യുന്നു.
ഡാറ്റാബേസ് കണക്ഷൻ പൂളിംഗ്
ഡാറ്റാബേസ് കണക്ഷനുകൾ കാര്യക്ഷമമായി കൈകാര്യം ചെയ്യാൻ SQLAlchemy കണക്ഷൻ പൂളിംഗ് ഉപയോഗിക്കുന്നു. ഒരു കണക്ഷൻ പൂൾ ഡാറ്റാബേസിലേക്ക് തുറന്ന കണക്ഷനുകളുടെ ഒരു കൂട്ടം നിലനിർത്തുന്നു, ഇത് ഓരോ അഭ്യർത്ഥനയ്ക്കും പുതിയ കണക്ഷനുകൾ സൃഷ്ടിക്കുന്നതിന് പകരം നിലവിലുള്ള കണക്ഷനുകൾ വീണ്ടും ഉപയോഗിക്കാൻ ആപ്ലിക്കേഷനുകളെ അനുവദിക്കുന്നു. ഇത് പ്രകടനം ഗണ്യമായി മെച്ചപ്പെടുത്താൻ കഴിയും, പ്രത്യേകിച്ചും വലിയ അളവിലുള്ള ഒരേസമയം വരുന്ന അഭ്യർത്ഥനകൾ കൈകാര്യം ചെയ്യുന്ന ആപ്ലിക്കേഷനുകളിൽ.
SQLAlchemy-യുടെ `create_engine()` ഫംഗ്ഷൻ സ്വയമേവ ഒരു കണക്ഷൻ പൂൾ സൃഷ്ടിക്കുന്നു. `create_engine()` ലേക്ക് ആർഗ്യുമെന്റുകൾ കൈമാറിക്കൊണ്ട് നിങ്ങൾക്ക് കണക്ഷൻ പൂൾ ക്രമീകരിക്കാൻ കഴിയും.
സാധാരണ കണക്ഷൻ പൂൾ പാരാമീറ്ററുകൾ ഇവയാണ്:
- pool_size: പൂളിലെ പരമാവധി കണക്ഷനുകളുടെ എണ്ണം.
- max_overflow: pool_size-ന് അപ്പുറം സൃഷ്ടിക്കാൻ കഴിയുന്ന കണക്ഷനുകളുടെ എണ്ണം.
- pool_recycle: ഒരു കണക്ഷൻ റീസൈക്കിൾ ചെയ്യുന്നതിനുള്ള സെക്കൻഡുകളുടെ എണ്ണം.
- pool_timeout: ഒരു കണക്ഷൻ ലഭ്യമാകുന്നതിനായി കാത്തിരിക്കേണ്ട സെക്കൻഡുകളുടെ എണ്ണം.
engine = create_engine('postgresql://user:password@host:port/database',
pool_size=5, #Maximum pool size
max_overflow=10, #Maximum overflow
pool_recycle=3600, #Recycle connections after 1 hour
pool_timeout=30
)
പ്രധാനം: നിങ്ങളുടെ ആപ്ലിക്കേഷന്റെ ആവശ്യകതകളും നിങ്ങളുടെ ഡാറ്റാബേസ് സെർവറിന്റെ കഴിവുകളും അടിസ്ഥാനമാക്കി ഉചിതമായ കണക്ഷൻ പൂൾ ക്രമീകരണങ്ങൾ തിരഞ്ഞെടുക്കുക. തെറ്റായി ക്രമീകരിച്ച കണക്ഷൻ പൂൾ പ്രകടന പ്രശ്നങ്ങൾക്കോ കണക്ഷൻ തീർന്നുപോകുന്നതിനോ കാരണമായേക്കാം.
അസിൻക്രണസ് ട്രാൻസാക്ഷനുകൾ (Async SQLAlchemy)
FastAPI അല്ലെങ്കിൽ AsyncIO പോലുള്ള അസിൻക്രണസ് ഫ്രെയിംവർക്കുകൾ ഉപയോഗിച്ച് നിർമ്മിച്ച ആധുനിക ആപ്ലിക്കേഷനുകൾക്ക് ഉയർന്ന കൺകറൻസി ആവശ്യമുള്ളതിനാൽ, SQLAlchemy-ക്ക് Async SQLAlchemy എന്ന പേരിൽ ഒരു അസിൻക്രണസ് പതിപ്പ് ലഭ്യമാണ്.
Async SQLAlchemy, SQLAlchemy-യുടെ പ്രധാന ഘടകങ്ങളുടെ അസിൻക്രണസ് പതിപ്പുകൾ നൽകുന്നു, ഇത് ഇവന്റ് ലൂപ്പിനെ തടസ്സപ്പെടുത്താതെ ഡാറ്റാബേസ് പ്രവർത്തനങ്ങൾ നടത്താൻ നിങ്ങളെ അനുവദിക്കുന്നു. ഇത് നിങ്ങളുടെ ആപ്ലിക്കേഷനുകളുടെ പ്രകടനവും സ്കേലബിലിറ്റിയും ഗണ്യമായി മെച്ചപ്പെടുത്താൻ കഴിയും.
Async SQLAlchemy ഉപയോഗിക്കുന്നതിന്റെ ഒരു അടിസ്ഥാന ഉദാഹരണം ഇതാ:
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import declarative_base
from sqlalchemy import Column, Integer, String
import asyncio
# Database setup (replace with your actual database URL)
db_url = 'postgresql+asyncpg://user:password@host:port/database'
engine = create_async_engine(db_url, echo=False)
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
email = Column(String)
def __repr__(self):
return f"<User(name='{self.name}', email='{self.email}')>"
async def create_db_and_tables():
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
async def add_user(name, email):
async with AsyncSession(engine) as session:
new_user = User(name=name, email=email)
session.add(new_user)
await session.commit()
async def main():
await create_db_and_tables()
await add_user("Async User", "async.user@example.com")
if __name__ == "__main__":
asyncio.run(main())
സിൻക്രണസ് SQLAlchemy-യിൽ നിന്നുള്ള പ്രധാന വ്യത്യാസങ്ങൾ:
- `create_engine`-ന് പകരം `create_async_engine` ഉപയോഗിക്കുന്നു.
- `Session`-ന് പകരം `AsyncSession` ഉപയോഗിക്കുന്നു.
- എല്ലാ ഡാറ്റാബേസ് പ്രവർത്തനങ്ങളും അസിൻക്രണസ് ആണ്, `await` ഉപയോഗിച്ച് കാത്തിരിക്കണം.
- അസിൻക്രണസ് ഡാറ്റാബേസ് ഡ്രൈവറുകൾ (ഉദാഹരണത്തിന്, PostgreSQL-നുള്ള `asyncpg`) ഉപയോഗിക്കണം.
പ്രധാനം: Async SQLAlchemy-ക്ക് അസിൻക്രണസ് പ്രവർത്തനങ്ങളെ പിന്തുണയ്ക്കുന്ന ഒരു ഡാറ്റാബേസ് ഡ്രൈവർ ആവശ്യമാണ്. നിങ്ങൾ ശരിയായ ഡ്രൈവർ ഇൻസ്റ്റാൾ ചെയ്യുകയും ക്രമീകരിക്കുകയും ചെയ്തിട്ടുണ്ടെന്ന് ഉറപ്പാക്കുക.
ഉപസംഹാരം
ഡാറ്റാബേസുകളുമായി സംവദിക്കുന്ന ശക്തവും വിശ്വസനീയവുമായ പൈത്തൺ ആപ്ലിക്കേഷനുകൾ നിർമ്മിക്കുന്നതിന് SQLAlchemy സെഷൻ, ട്രാൻസാക്ഷൻ മാനേജ്മെന്റ് എന്നിവയിൽ പ്രാവീണ്യം നേടേണ്ടത് അത്യാവശ്യമാണ്. സെഷനുകൾ, ട്രാൻസാക്ഷനുകൾ, ഐസൊലേഷൻ ലെവലുകൾ, കൺകറൻസി എന്നിവയുടെ ആശയങ്ങൾ മനസ്സിലാക്കുന്നതിലൂടെയും എക്സപ്ഷൻ കൈകാര്യം ചെയ്യുന്നതിനും കണക്ഷൻ പൂളിംഗിനുമുള്ള മികച്ച രീതികൾ പിന്തുടരുന്നതിലൂടെയും നിങ്ങൾക്ക് ഡാറ്റാ സമഗ്രത ഉറപ്പാക്കാനും നിങ്ങളുടെ ആപ്ലിക്കേഷനുകളുടെ പ്രകടനം ഒപ്റ്റിമൈസ് ചെയ്യാനും കഴിയും.
നിങ്ങൾ ഒരു ചെറിയ വെബ് ആപ്ലിക്കേഷൻ നിർമ്മിക്കുകയാണെങ്കിലും ഒരു വലിയ എന്റർപ്രൈസ് സിസ്റ്റം നിർമ്മിക്കുകയാണെങ്കിലും, നിങ്ങളുടെ ഡാറ്റാബേസ് ഇടപെടലുകൾ ഫലപ്രദമായി കൈകാര്യം ചെയ്യാൻ ആവശ്യമായ ഉപകരണങ്ങൾ SQLAlchemy നൽകുന്നു. നിങ്ങളുടെ ആപ്ലിക്കേഷനുകളുടെ വിശ്വാസ്യത ഉറപ്പാക്കാൻ എപ്പോഴും ഡാറ്റാ സമഗ്രതയ്ക്ക് മുൻഗണന നൽകുകയും സാധ്യതയുള്ള പിശകുകൾ ശ്രദ്ധയോടെ കൈകാര്യം ചെയ്യുകയും ചെയ്യുക.
ഇനിപ്പറയുന്ന വിപുലമായ വിഷയങ്ങൾ പര്യവേക്ഷണം ചെയ്യുന്നത് പരിഗണിക്കുക:
- ടു-ഫേസ് കമ്മിറ്റ് (2PC): ഒന്നിലധികം ഡാറ്റാബേസുകളിലായി വ്യാപിച്ചുകിടക്കുന്ന ട്രാൻസാക്ഷനുകൾക്ക്.
- ഷാർഡിംഗ്: ഒന്നിലധികം ഡാറ്റാബേസ് സെർവറുകളിലായി ഡാറ്റ വിതരണം ചെയ്യാൻ.
- ഡാറ്റാബേസ് മൈഗ്രേഷൻ: ഡാറ്റാബേസ് സ്കീമ മാറ്റങ്ങൾ കൈകാര്യം ചെയ്യാൻ Alembic പോലുള്ള ഉപകരണങ്ങൾ ഉപയോഗിച്ച്.