Visaptverošs ceļvedis par SQLAlchemy sesiju pārvaldību Python, fokusējoties uz darījumu apstrādes metodēm datu integritātes un konsekvences nodrošināšanai.
Python SQLAlchemy sesiju pārvaldība: Darījumu apstrādes apgūšana datu integritātes nodrošināšanai
SQLAlchemy ir jaudīga un elastīga Python bibliotēka, kas nodrošina visaptverošu rīku kopumu mijiedarbībai ar datubāzēm. SQLAlchemy pamatā ir sesijas jēdziens, kas darbojas kā sagatavošanas zona visām darbībām, ko veicat ar savu datubāzi. Pareiza sesijas un darījumu pārvaldība ir būtiska, lai uzturētu datu integritāti un nodrošinātu konsekventu datubāzes darbību, jo īpaši sarežģītās lietojumprogrammās, kas apstrādā vienlaicīgus pieprasījumus.
SQLAlchemy sesiju izpratne
SQLAlchemy sesija ir darba vienība, saruna ar datubāzi. Tā izseko objektos veiktās izmaiņas, ļaujot tās saglabāt datubāzē kā vienu atomisku operāciju. Iedomājieties to kā darba vietu, kurā veicat datu modifikācijas pirms to oficiālas saglabāšanas. Bez labi pārvaldītas sesijas jūs riskējat ar datu neatbilstībām un iespējamu korupciju.
Sesijas izveide
Pirms sākt mijiedarbību ar datubāzi, jums ir jāizveido sesija. Tas ietver savienojuma izveidi ar datubāzi, izmantojot SQLAlchemy dzinēju.
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""
# Create the table in the database
Base.metadata.create_all(engine)
# Create a session class
Session = sessionmaker(bind=engine)
# Instantiate a session
session = Session()
Šajā piemērā:
- Mēs importējam nepieciešamos SQLAlchemy moduļus.
- Mēs definējam datubāzes savienojuma virkni (`db_url`). Šis piemērs vienkāršības labad izmanto SQLite datubāzi atmiņā, taču jums tā būtu jāaizstāj ar savienojuma virkni, kas piemērota jūsu datubāzes sistēmai (piemēram, PostgreSQL, MySQL). Konkrētais formāts atšķiras atkarībā no datubāzes dzinēja un draivera, ko izmantojat. Pareiza savienojuma virknes formāta iegūšanai konsultējieties ar SQLAlchemy dokumentāciju un jūsu datubāzes nodrošinātāja dokumentāciju.
- Mēs izveidojam `engine`, izmantojot `create_engine()`. Dzinējs ir atbildīgs par savienojumu kopas pārvaldību un saziņu ar datubāzi. Parametrs `echo=True` var būt noderīgs atkļūdošanai, jo tas izvadīs ģenerētos SQL paziņojumus uz konsoli.
- Mēs definējam bāzes klasi (`Base`), izmantojot `declarative_base()`. Tā tiek izmantota kā bāzes klase visiem mūsu SQLAlchemy modeļiem.
- Mēs definējam `User` modeli, kartējot to uz datubāzes tabulu ar nosaukumu `users`.
- Mēs izveidojam tabulu datubāzē, izmantojot `Base.metadata.create_all(engine)`.
- Mēs izveidojam sesijas klasi, izmantojot `sessionmaker(bind=engine)`. Tas konfigurē sesijas klasi, lai tā izmantotu norādīto dzinēju.
- Visbeidzot, mēs inicializējam sesiju, izmantojot `Session()`.
Darījumu izpratne
Darījums ir datubāzes operāciju secība, kas tiek apstrādāta kā viena loģiska darba vienība. Darījumi atbilst ACID īpašībām:
- Atomiskums: Visas darījuma operācijas vai nu pilnībā izdodas, vai pilnībā neizdodas. Ja kāda darījuma daļa neizdodas, viss darījums tiek atcelts (rolled back).
- Konsekvence: Darījumam jāsaglabā datubāze derīgā stāvoklī. Tas nedrīkst pārkāpt nekādus datubāzes ierobežojumus vai noteikumus.
- Izolācija: Vienlaicīgi darījumi ir izolēti viens no otra. Izmaiņas, ko veicis viens darījums, nav redzamas citiem darījumiem, līdz pirmais darījums ir apstiprināts (committed).
- Izturība: Kad darījums ir apstiprināts (committed), tā izmaiņas ir pastāvīgas un saglabāsies pat sistēmas kļūmju gadījumā.
SQLAlchemy nodrošina mehānismus darījumu pārvaldībai, nodrošinot šo ACID īpašību uzturēšanu.
Pamata darījumu apstrāde
Visbiežākās darījumu operācijas ir commit un rollback.
Darījumu apstiprināšana (Committing Transactions)
Kad visas operācijas darījuma ietvaros ir veiksmīgi pabeigtas, jūs apstiprināt darījumu (commit). Tas saglabā izmaiņas datubāzē.
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()
Šajā piemērā:
- Mēs pievienojam jaunu `User` objektu sesijai.
- Mēs izsaucam `session.commit()`, lai saglabātu izmaiņas datubāzē.
- Mēs iekļaujam kodu `try...except...finally` blokā, lai apstrādātu iespējamos izņēmumus.
- Ja rodas izņēmums, mēs izsaucam `session.rollback()`, lai atceltu visas darījuma laikā veiktās izmaiņas.
- Mēs vienmēr izsaucam `session.close()` `finally` blokā, lai atbrīvotu sesiju un atgrieztu savienojumu savienojumu kopā. Tas ir ļoti svarīgi, lai izvairītos no resursu noplūdēm. Sesiju neaizvēršana var izraisīt savienojumu izsīkumu un lietojumprogrammas nestabilitāti.
Darījumu atcelšana (Rolling Back Transactions)
Ja darījuma laikā rodas kļūda vai ja jūs nolemjat, ka izmaiņas nedrīkst tikt saglabātas, jūs atceļat darījumu (rollback). Tas atgriež datubāzi tās stāvoklī pirms darījuma sākuma.
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()
Šajā piemērā, ja `invalid_user` pievienošana izraisa izņēmumu (piemēram, datubāzes ierobežojuma pārkāpuma dēļ), `session.rollback()` izsaukums atcels mēģināto ievietošanu, atstājot datubāzi nemainīgu.
Uzlabota darījumu pārvaldība
`with` paziņojuma izmantošana darījumu darbības jomai
Pythoniskāks un stabilāks veids, kā pārvaldīt darījumus, ir izmantot `with` paziņojumu. Tas nodrošina, ka sesija tiek pareizi aizvērta, pat ja rodas izņēmumi.
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).")
Funkcija `session_scope` ir konteksta pārvaldnieks. Ienākot `with` blokā, tiek izveidota jauna sesija. Izejot no `with` bloka, sesija tiek vai nu apstiprināta (ja nav radušies izņēmumi), vai atcelta (ja ir radies izņēmums). Sesija vienmēr tiek aizvērta `finally` blokā.
Ligzdotie darījumi (Savepoints)
SQLAlchemy atbalsta ligzdotos darījumus, izmantojot saglabāšanas punktus (savepoints). Saglabāšanas punkts ļauj atcelt darījumu līdz noteiktam punktam lielākā darījumā, neietekmējot visu darījumu.
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
Šajā piemērā:
- Mēs sākam ārējo darījumu, izmantojot `session_scope()`.
- Mēs pievienojam `user1` sesijai un pārsūtām izmaiņas uz datubāzi. `flush()` nosūta izmaiņas datubāzes serverim, bet tās *nesaglabā*. Tas ļauj jums redzēt, vai izmaiņas ir derīgas (piemēram, nav ierobežojumu pārkāpumu), pirms visa darījuma saglabāšanas.
- Mēs izveidojam saglabāšanas punktu (savepoint), izmantojot `session.begin_nested()`.
- Ligzdotā darījuma ietvaros mēs pievienojam `user2` un simulējam kļūdu.
- Mēs atceļam ligzdoto darījumu līdz saglabāšanas punktam, izmantojot `savepoint.rollback()`. Tas atceļ tikai ligzdotā darījuma laikā veiktās izmaiņas (t.i., `user2` pievienošanu).
- Mēs turpinām ārējo darījumu un pievienojam `user3`.
- Ārējais darījums tiek apstiprināts (committed), saglabājot `user1` un `user3` datubāzē, savukārt `user2` tiek atmests sakarā ar saglabāšanas punkta atcelšanu.
Izolācijas līmeņu kontrole
Izolācijas līmeņi nosaka, cik lielā mērā vienlaicīgi darījumi ir izolēti viens no otra. Augstāki izolācijas līmeņi nodrošina lielāku datu konsekvenci, bet var samazināt vienlaicīgumu un veiktspēju. SQLAlchemy ļauj kontrolēt jūsu darījumu izolācijas līmeni.
Parastie izolācijas līmeņi ietver:
- Nekomitētas lasīšanas (Read Uncommitted): Zemākais izolācijas līmenis. Darījumi var redzēt citu darījumu nekomitētas izmaiņas. Tas var izraisīt netīras lasīšanas (dirty reads).
- Komitētas lasīšanas (Read Committed): Darījumi var redzēt tikai citu darījumu komitētas izmaiņas. Tas novērš netīras lasīšanas, bet var izraisīt neatkārtojamas lasīšanas (non-repeatable reads) un fantoma lasīšanas (phantom reads).
- Atkārtojamas lasīšanas (Repeatable Read): Darījumi var redzēt tos pašus datus visā darījuma laikā, pat ja citi darījumi tos modificē. Tas novērš netīras lasīšanas un neatkārtojamas lasīšanas, bet var izraisīt fantoma lasīšanas.
- Serializējams (Serializable): Augstākais izolācijas līmenis. Darījumi ir pilnībā izolēti viens no otra. Tas novērš netīras lasīšanas, neatkārtojamas lasīšanas un fantoma lasīšanas, bet var ievērojami samazināt vienlaicīgumu.
Noklusējuma izolācijas līmenis ir atkarīgs no datubāzes sistēmas. Jūs varat iestatīt izolācijas līmeni, veidojot dzinēju vai sākot darījumu.
Piemērs (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.
Svarīgi: Izolācijas līmeņu iestatīšanas metode ir specifiska datubāzei. Pareizai sintaksei skatiet savas datubāzes dokumentāciju. Nepareiza izolācijas līmeņu iestatīšana var izraisīt neparedzētu uzvedību vai kļūdas.
Vienlaicīguma apstrāde
Kad vairāki lietotāji vai procesi vienlaicīgi piekļūst vieniem un tiem pašiem datiem, ir ļoti svarīgi pareizi apstrādāt vienlaicīgumu, lai novērstu datu bojājumus un nodrošinātu datu konsekvenci. SQLAlchemy nodrošina vairākus mehānismus vienlaicīguma apstrādei, tostarp optimistisko bloķēšanu un pesimistisko bloķēšanu.
Optimistiskā bloķēšana
Optimistiskā bloķēšana pieņem, ka konflikti ir reti. Tā pārbauda citu darījumu veiktās modifikācijas pirms darījuma apstiprināšanas. Ja tiek konstatēts konflikts, darījums tiek atcelts.
Lai ieviestu optimistisko bloķēšanu, jūs parasti pievienojat versijas kolonnu savai tabulai. Šī kolonna tiek automātiski palielināta ikreiz, kad rinda tiek atjaunināta.
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""
#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()
Šajā piemērā:
- Mēs pievienojam `version` kolonnu `Article` modelim.
- Pirms raksta atjaunināšanas mēs saglabājam pašreizējo versijas numuru.
- `UPDATE` paziņojumā mēs iekļaujam `WHERE` klauzulu, kas pārbauda, vai versijas kolonna joprojām ir vienāda ar saglabāto versijas numuru. `synchronize_session=False` neļauj SQLAlchemy atkārtoti ielādēt atjaunināto objektu; mēs skaidri apstrādājam versiju.
- Ja versijas kolonna ir mainīta citā darījumā, `UPDATE` paziņojums neietekmēs nevienu rindu (rows_affected būs 0), un mēs izraisām izņēmumu.
- Mēs atceļam darījumu un paziņojam lietotājam, ka ir radies konflikts.
Pesimistiskā bloķēšana
Pesimistiskā bloķēšana pieņem, ka konflikti ir iespējami. Tā iegūst bloķēšanu rindā vai tabulā pirms tās modificēšanas. Tas neļauj citiem darījumiem modificēt datus, līdz bloķēšana tiek atbrīvota.
SQLAlchemy nodrošina vairākas funkcijas bloķēšanas iegūšanai, piemēram, `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"- "
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
Šajā piemērā:
- Mēs izmantojam `with_for_update()`, lai iegūtu bloķēšanu `Item` rindā pirms tās atjaunināšanas. Tas neļauj citiem darījumiem modificēt rindu, līdz pašreizējais darījums tiek apstiprināts (committed) vai atcelts (rolled back). Funkcija `with_for_update()` ir specifiska datubāzei; detalizētu informāciju skatiet savas datubāzes dokumentācijā. Dažām datubāzēm var būt atšķirīgi bloķēšanas mehānismi vai sintakse.
Svarīgi: Pesimistiskā bloķēšana var samazināt vienlaicīgumu un veiktspēju, tāpēc izmantojiet to tikai tad, kad tas ir nepieciešams.
Labākā prakse izņēmumu apstrādē
Pareiza izņēmumu apstrāde ir kritiski svarīga, lai nodrošinātu datu integritāti un novērstu lietojumprogrammu avārijas. Vienmēr iekļaujiet savas datubāzes operācijas `try...except` blokos un atbilstoši apstrādājiet izņēmumus.
Šeit ir dažas labākās prakses izņēmumu apstrādei:
- Tveriet specifiskus izņēmumus: Izvairieties tvert vispārīgus izņēmumus, piemēram, `Exception`. Tveriet specifiskus izņēmumus, piemēram, `sqlalchemy.exc.IntegrityError` vai `sqlalchemy.exc.OperationalError`, lai dažādus kļūdu veidus apstrādātu atšķirīgi.
- Atceliet darījumus: Vienmēr atceliet darījumu, ja rodas izņēmums.
- Žurnālējiet izņēmumus: Žurnālējiet izņēmumus, lai palīdzētu diagnosticēt un novērst problēmas. Iekļaujiet pēc iespējas vairāk konteksta savos žurnālos (piemēram, lietotāja ID, ievades datus, laika zīmogu).
- Atkārtoti izraisiet izņēmumus, kad tas ir piemēroti: Ja nevarat apstrādāt izņēmumu, atkārtoti izraisiet to, lai augstāka līmeņa apstrādātājs varētu ar to tikt galā.
- Sakārtojiet resursus: Vienmēr aizveriet sesiju un atbrīvojiet citus resursus `finally` blokā.
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""
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()
Šajā piemērā:
- Mēs konfigurējam žurnālēšanu, lai ierakstītu notikumus procesa laikā.
- Mēs tveram specifiskus izņēmumus, piemēram, `IntegrityError` (ierobežojumu pārkāpumiem) un `OperationalError` (savienojuma kļūdām).
- Mēs atceļam darījumu `except` blokos.
- Mēs žurnālējam izņēmumus, izmantojot `logging` moduli. Metodes `logging.exception()` automātiski iekļauj steka izsekošanu žurnāla ziņojumā.
- Mēs atkārtoti izraisām izņēmumu, ja nevaram to apstrādāt.
- Mēs aizveram sesiju `finally` blokā.
Datubāzes savienojumu kopas izmantošana
SQLAlchemy izmanto savienojumu kopu, lai efektīvi pārvaldītu datubāzes savienojumus. Savienojumu kopa uztur atvērtu savienojumu kopumu ar datubāzi, ļaujot lietojumprogrammām atkārtoti izmantot esošos savienojumus, nevis veidot jaunus katram pieprasījumam. Tas var ievērojami uzlabot veiktspēju, īpaši lietojumprogrammās, kas apstrādā lielu skaitu vienlaicīgu pieprasījumu.
SQLAlchemy funkcija `create_engine()` automātiski izveido savienojumu kopu. Jūs varat konfigurēt savienojumu kopu, nododot argumentus funkcijai `create_engine()`.
Parastie savienojumu kopas parametri ietver:
- pool_size: Maksimālais savienojumu skaits kopā.
- max_overflow: Savienojumu skaits, ko var izveidot virs pool_size.
- pool_recycle: Sekunžu skaits, pēc kura savienojums tiek reciklēts.
- pool_timeout: Sekunžu skaits, kas jāgaida, līdz savienojums kļūst pieejams.
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
)
Svarīgi: Izvēlieties atbilstošus savienojumu kopas iestatījumus, pamatojoties uz jūsu lietojumprogrammas vajadzībām un datubāzes servera iespējām. Slikti konfigurēta savienojumu kopa var izraisīt veiktspējas problēmas vai savienojumu izsīkumu.
Asinhronie darījumi (Async SQLAlchemy)
Mūsdienīgām lietojumprogrammām, kurām nepieciešama augsta vienlaicīgums, īpaši tām, kas veidotas ar asinhroniem ietvariem, piemēram, FastAPI vai AsyncIO, SQLAlchemy piedāvā asinhrono versiju, ko sauc par Async SQLAlchemy.
Async SQLAlchemy nodrošina galveno SQLAlchemy komponentu asinhronās versijas, kas ļauj veikt datubāzes operācijas, nebloķējot notikumu cilpu. Tas var ievērojami uzlabot jūsu lietojumprogrammu veiktspēju un mērogojamību.
Šeit ir pamata piemērs Async SQLAlchemy izmantošanai:
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""
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())
Galvenās atšķirības no sinhronā SQLAlchemy:
- `create_async_engine` tiek izmantots `create_engine` vietā.
- `AsyncSession` tiek izmantots `Session` vietā.
- Visas datubāzes operācijas ir asinhronas un tām jābūt gaidītām, izmantojot `await`.
- Jāizmanto asinhronie datubāzes draiveri (piemēram, `asyncpg` PostgreSQL).
Svarīgi: Async SQLAlchemy nepieciešams datubāzes draiveris, kas atbalsta asinhronās operācijas. Pārliecinieties, vai jums ir pareizais draiveris instalēts un konfigurēts.
Secinājums
SQLAlchemy sesiju un darījumu pārvaldības apgūšana ir būtiska, lai veidotu stabilas un uzticamas Python lietojumprogrammas, kas mijiedarbojas ar datubāzēm. Izprotot sesiju, darījumu, izolācijas līmeņu un vienlaicīguma jēdzienus, kā arī ievērojot labāko praksi izņēmumu apstrādē un savienojumu kopas izmantošanā, jūs varat nodrošināt datu integritāti un optimizēt savu lietojumprogrammu veiktspēju.
Neatkarīgi no tā, vai veidojat mazu tīmekļa lietojumprogrammu vai liela mēroga uzņēmuma sistēmu, SQLAlchemy nodrošina nepieciešamos rīkus efektīvai datubāzes mijiedarbības pārvaldībai. Atcerieties vienmēr piešķirt prioritāti datu integritātei un graciozi apstrādāt iespējamās kļūdas, lai nodrošinātu jūsu lietojumprogrammu uzticamību.
Apsveriet iespēju izpētīt progresīvas tēmas, piemēram:
- Divu fāžu komitēšana (2PC): Darījumiem, kas aptver vairākas datubāzes.
- Sadališana (Sharding): Datu sadalīšanai starp vairākiem datubāzes serveriem.
- Datubāzes migrācijas: Rīku, piemēram, Alembic, izmantošana datubāzes shēmas izmaiņu pārvaldībai.