பைதான் 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 மாடல்களுக்கும் அடிப்படை வகுப்பாகப் பயன்படுத்தப்படுகிறது.
- ஒரு `User` மாடலை வரையறுக்கிறோம், அதை `users` என்ற தரவுத்தள அட்டவணைக்கு மேப் செய்கிறோம்.
- `Base.metadata.create_all(engine)` பயன்படுத்தி தரவுத்தளத்தில் அட்டவணையை உருவாக்குகிறோம்.
- `sessionmaker(bind=engine)` பயன்படுத்தி ஒரு அமர்வு வகுப்பை உருவாக்குகிறோம். இது குறிப்பிட்ட இன்ஜினைப் பயன்படுத்த அமர்வு வகுப்பை உள்ளமைக்கிறது.
- இறுதியாக, `Session()` பயன்படுத்தி ஒரு அமர்வை உருவாக்குகிறோம்.
பரிவர்த்தனைகளைப் புரிந்துகொள்வது
ஒரு பரிவர்த்தனை என்பது ஒரு பணியின் ஒற்றை தர்க்க அலகாகக் கருதப்படும் தரவுத்தள செயல்பாடுகளின் ஒரு தொடர் ஆகும். பரிவர்த்தனைகள் ACID பண்புகளுக்கு இணங்குகின்றன:
- அணுத்தன்மை (Atomicity): பரிவர்த்தனையில் உள்ள அனைத்து செயல்பாடுகளும் முழுமையாக வெற்றிபெறும் அல்லது முழுமையாக தோல்வியடையும். பரிவர்த்தனையின் எந்தப் பகுதியும் தோல்வியடைந்தால், முழு பரிவர்த்தனையும் ரோல்பேக் செய்யப்படும்.
- நிலைத்தன்மை (Consistency): பரிவர்த்தனை தரவுத்தளத்தை ஒரு சரியான நிலையில் பராமரிக்க வேண்டும். இது எந்த தரவுத்தள கட்டுப்பாடுகளையும் அல்லது விதிகளையும் மீறக்கூடாது.
- தனிமைப்படுத்தல் (Isolation): ஒரே நேரத்தில் நிகழும் பரிவர்த்தனைகள் ஒன்றிலிருந்து மற்றொன்று தனிமைப்படுத்தப்படுகின்றன. ஒரு பரிவர்த்தனையால் செய்யப்பட்ட மாற்றங்கள் முதல் பரிவர்த்தனை கமிட் ஆகும் வரை மற்ற பரிவர்த்தனைகளுக்குத் தெரியாது.
- நீடித்துழைப்பு (Durability): ஒரு பரிவர்த்தனை கமிட் செய்யப்பட்டதும், அதன் மாற்றங்கள் நிரந்தரமானவை மற்றும் கணினி தோல்விகளிலிருந்தும் தப்பிக்கும்.
SQLAlchemy, இந்த ACID பண்புகளைப் பராமரிப்பதை உறுதிசெய்து, பரிவர்த்தனைகளை நிர்வகிப்பதற்கான வழிமுறைகளை வழங்குகிறது.
அடிப்படை பரிவர்த்தனை கையாளுதல்
மிகவும் பொதுவான பரிவர்த்தனை செயல்பாடுகள் கமிட் (commit) மற்றும் ரோல்பேக் (rollback) ஆகும்.
பரிவர்த்தனைகளை கமிட் செய்தல்
ஒரு பரிவர்த்தனைக்குள் உள்ள அனைத்து செயல்பாடுகளும் வெற்றிகரமாக முடிந்ததும், நீங்கள் பரிவர்த்தனையை கமிட் செய்கிறீர்கள். இது மாற்றங்களை தரவுத்தளத்தில் நிலைநிறுத்துகிறது.
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()` ஐ அழைக்கிறோம்.
- அமர்வை விடுவித்து, இணைப்பை இணைப்பு பூலுக்குத் திருப்பி அனுப்ப `session.close()` ஐ `finally` தொகுதியில் எப்போதும் அழைக்கிறோம். வளக் கசிவுகளைத் தவிர்க்க இது முக்கியம். அமர்வுகளை மூடத் தவறினால் இணைப்பு தீர்ந்துபோகும் மற்றும் பயன்பாட்டின் நிலைத்தன்மை பாதிக்கப்படும்.
பரிவர்த்தனைகளை ரோல்பேக் செய்தல்
ஒரு பரிவர்த்தனையின் போது ஏதேனும் பிழை ஏற்பட்டால், அல்லது மாற்றங்கள் நிலைநிறுத்தப்படக்கூடாது என்று நீங்கள் முடிவு செய்தால், நீங்கள் பரிவர்த்தனையை ரோல்பேக் செய்கிறீர்கள். இது பரிவர்த்தனை தொடங்குவதற்கு முன் இருந்த நிலைக்கு தரவுத்தளத்தைத் திருப்புகிறது.
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` கூற்றைப் பயன்படுத்துவதாகும். இது பிழைகள் ஏற்பட்டாலும் அமர்வு சரியாக மூடப்படுவதை உறுதி செய்கிறது.
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` செய்கிறோம். `flush()` மாற்றங்களை தரவுத்தள சேவையகத்திற்கு அனுப்புகிறது, ஆனால் அவற்றை *கமிட்* செய்யாது. முழு பரிவர்த்தனையையும் கமிட் செய்வதற்கு முன் மாற்றங்கள் சரியானதா (எ.கா., கட்டுப்பாட்டு மீறல்கள் இல்லை) என்பதைப் பார்க்க இது உங்களை அனுமதிக்கிறது.
- `session.begin_nested()` பயன்படுத்தி ஒரு சேவ் பாயிண்ட்டை உருவாக்குகிறோம்.
- கூடுதல் பரிவர்த்தனைக்குள், `user2` ஐச் சேர்த்து ஒரு பிழையை உருவகப்படுத்துகிறோம்.
- `savepoint.rollback()` ஐப் பயன்படுத்தி கூடுதல் பரிவர்த்தனையை சேவ் பாயிண்ட்டிற்கு ரோல்பேக் செய்கிறோம். இது கூடுதல் பரிவர்த்தனைக்குள் செய்யப்பட்ட மாற்றங்களை மட்டுமே ரத்து செய்கிறது (அதாவது, `user2` ஐ சேர்த்தல்).
- வெளிப் பரிவர்த்தனையைத் தொடர்கிறோம் மற்றும் `user3` ஐச் சேர்க்கிறோம்.
- சேவ் பாயிண்ட் ரோல்பேக் காரணமாக `user2` நிராகரிக்கப்படும்போது, வெளிப் பரிவர்த்தனை கமிட் செய்யப்பட்டு, `user1` மற்றும் `user3` தரவுத்தளத்தில் நிலைநிறுத்தப்படுகின்றன.
தனிமைப்படுத்தல் நிலைகளைக் கட்டுப்படுத்துதல்
தனிமைப்படுத்தல் நிலைகள், ஒரே நேரத்தில் நிகழும் பரிவர்த்தனைகள் ஒன்றிலிருந்து மற்றொன்று தனிமைப்படுத்தப்படும் அளவை வரையறுக்கின்றன. அதிக தனிமைப்படுத்தல் நிலைகள் சிறந்த தரவு நிலைத்தன்மையை வழங்குகின்றன, ஆனால் ஒருமித்த செயல்பாடு மற்றும் செயல்திறனைக் குறைக்கலாம். SQLAlchemy உங்கள் பரிவர்த்தனைகளின் தனிமைப்படுத்தல் நிலையை கட்டுப்படுத்த உங்களை அனுமதிக்கிறது.
பொதுவான தனிமைப்படுத்தல் நிலைகள்:
- Read Uncommitted: மிகக் குறைந்த தனிமைப்படுத்தல் நிலை. பரிவர்த்தனைகள் மற்ற பரிவர்த்தனைகளால் செய்யப்பட்ட கமிட் செய்யப்படாத மாற்றங்களைப் பார்க்க முடியும். இது அசுத்தமான வாசிப்புகளுக்கு (dirty reads) வழிவகுக்கும்.
- Read Committed: பரிவர்த்தனைகள் மற்ற பரிவர்த்தனைகளால் செய்யப்பட்ட கமிட் செய்யப்பட்ட மாற்றங்களை மட்டுமே பார்க்க முடியும். இது அசுத்தமான வாசிப்புகளைத் தடுக்கிறது, ஆனால் மீண்டும் செய்ய முடியாத வாசிப்புகள் (non-repeatable reads) மற்றும் மாய வாசிப்புகளுக்கு (phantom reads) வழிவகுக்கும்.
- 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, நம்பிக்கையான பூட்டுதல் (optimistic locking) மற்றும் அவநம்பிக்கையான பூட்டுதல் (pessimistic locking) உள்ளிட்ட பல ஒருமித்த செயல்பாட்டுக் கையாளும் வழிமுறைகளை வழங்குகிறது.
நம்பிக்கையான பூட்டுதல் (Optimistic Locking)
நம்பிக்கையான பூட்டுதல் மோதல்கள் அரிது என்று கருதுகிறது. ஒரு பரிவர்த்தனையை கமிட் செய்வதற்கு முன் மற்ற பரிவர்த்தனைகளால் செய்யப்பட்ட மாற்றங்களை இது சரிபார்க்கிறது. ஒரு மோதல் கண்டறியப்பட்டால், பரிவர்த்தனை ரோல்பேக் செய்யப்படும்.
நம்பிக்கையான பூட்டுதலைச் செயல்படுத்த, நீங்கள் பொதுவாக உங்கள் அட்டவணையில் ஒரு பதிப்பு நிரலைச் சேர்க்கிறீர்கள். இந்த நிரல் வரிசை புதுப்பிக்கப்படும்போதெல்லாம் தானாகவே அதிகரிக்கும்.
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 ஆக இருக்கும்), மேலும் நாம் ஒரு பிழையை எழுப்புகிறோம்.
- பரிவர்த்தனையை ரோல்பேக் செய்து, ஒரு மோதல் ஏற்பட்டுள்ளது என்று பயனருக்கு அறிவிக்கிறோம்.
அவநம்பிக்கையான பூட்டுதல் (Pessimistic Locking)
அவநம்பிக்கையான பூட்டுதல் மோதல்கள் ஏற்பட வாய்ப்புள்ளது என்று கருதுகிறது. இது ஒரு வரிசை அல்லது அட்டவணையை மாற்றும் முன் அதன் மீது ஒரு பூட்டைப் பெறுகிறது. பூட்டு விடுவிக்கப்படும் வரை மற்ற பரிவர்த்தனைகள் தரவை மாற்றுவதைத் இது தடுக்கிறது.
SQLAlchemy, `with_for_update()` போன்ற பூட்டுகளைப் பெறுவதற்கான பல செயல்பாடுகளை வழங்குகிறது.
# 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` போன்ற குறிப்பிட்ட பிழைகளைப் பிடிக்கவும்.
- பரிவர்த்தனைகளை ரோல்பேக் செய்யவும்: ஒரு பிழை ஏற்பட்டால் எப்போதும் பரிவர்த்தனையை ரோல்பேக் செய்யவும்.
- பிழைகளைப் பதிவு செய்யவும்: சிக்கல்களைக் கண்டறிந்து சரிசெய்ய உதவ பிழைகளைப் பதிவு செய்யவும். உங்கள் பதிவுகளில் முடிந்தவரை சூழலை (எ.கா., பயனர் ID, உள்ளீட்டுத் தரவு, நேர முத்திரை) சேர்க்கவும்.
- பொருத்தமானால் பிழைகளை மீண்டும் எழுப்பவும்: ஒரு பிழையை உங்களால் கையாள முடியாவிட்டால், ஒரு உயர்நிலை கையாளுபவர் அதைக் கையாள அனுமதிக்க அதை மீண்டும் எழுப்பவும்.
- வளங்களை சுத்தம் செய்யவும்: `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 வழங்குகிறது. உங்கள் பயன்பாடுகளின் நம்பகத்தன்மையை உறுதிப்படுத்த எப்போதும் தரவு ஒருமைப்பாட்டிற்கு முன்னுரிமை அளித்து, சாத்தியமான பிழைகளை நேர்த்தியாகக் கையாள நினைவில் கொள்ளுங்கள்.
மேம்பட்ட தலைப்புகளை ஆராய்வதைக் கருத்தில் கொள்ளவும்:
- இரு-கட்ட கமிட் (Two-Phase Commit - 2PC): பல தரவுத்தளங்களுக்கு இடையில் பரவியிருக்கும் பரிவர்த்தனைகளுக்கு.
- ஷார்டிங் (Sharding): பல தரவுத்தள சேவையகங்களுக்கு தரவை விநியோகிப்பதற்கு.
- தரவுத்தள இடமாற்றங்கள் (Database migrations): தரவுத்தள ஸ்கீமா மாற்றங்களை நிர்வகிக்க Alembic போன்ற கருவிகளைப் பயன்படுத்துதல்.