国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

python常用庫(kù)之?dāng)?shù)據(jù)庫(kù)orm框架之SQLAlchemy

這篇具有很好參考價(jià)值的文章主要介紹了python常用庫(kù)之?dāng)?shù)據(jù)庫(kù)orm框架之SQLAlchemy。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

python常用庫(kù)之?dāng)?shù)據(jù)庫(kù)orm框架之SQLAlchemy

一、什么是SQLAlchemy

官網(wǎng):https://www.sqlalchemy.org/

SQLAlchemy是一個(gè)基于Python實(shí)現(xiàn)的SQL工具包和ORM框架,提供了高層抽象來(lái)管理數(shù)據(jù)庫(kù)交互。

SQLAlchemy功能強(qiáng)大,可以省去很多手動(dòng)管理數(shù)據(jù)庫(kù)連接、資源、事務(wù)等重復(fù)工作,讓開(kāi)發(fā)者更加高效地使用數(shù)據(jù)庫(kù)。許多大型Python項(xiàng)目都選擇使用SQLAlchemy作為ORM框架。

SQLAlchemy 使用場(chǎng)景

SQLAlchemy是一個(gè)強(qiáng)大的Python ORM框架,主要應(yīng)用于以下場(chǎng)景:

  1. 數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)和操作:SQLAlchemy提供了高層抽象來(lái)操作數(shù)據(jù)庫(kù),可以避免寫(xiě)原生SQL語(yǔ)句。支持多種數(shù)據(jù)庫(kù)后端。
  2. ORM映射:建立Python類(lèi)與數(shù)據(jù)庫(kù)表的映射關(guān)系,簡(jiǎn)化數(shù)據(jù)模型的操作,支持聲明式操作。
  3. 復(fù)雜查詢(xún): SQLAlchemy提供豐富的查詢(xún)方式,如過(guò)濾、分組、聯(lián)結(jié)等,可以構(gòu)建復(fù)雜查詢(xún)。
  4. 異步查詢(xún):基于Greenlet等實(shí)現(xiàn)異步查詢(xún),提高查詢(xún)效率。
  5. 事務(wù)控制: 通過(guò)Session管理數(shù)據(jù)庫(kù)會(huì)話(huà)和事務(wù)。
  6. 工具集成:如數(shù)據(jù)遷移工具Alembic,可以實(shí)現(xiàn)Schema版本控制和遷移。
  7. 大數(shù)據(jù)集查詢(xún):基于Pagination實(shí)現(xiàn)數(shù)據(jù)分頁(yè),避免大量數(shù)據(jù)查詢(xún)內(nèi)存溢出。
  8. 多數(shù)據(jù)庫(kù)支持:支持Postgres、MySQL、Oracle等主流數(shù)據(jù)庫(kù)。
  9. Web框架集成:框架如Flask可以集成SQLAlchemy,便于Web應(yīng)用開(kāi)發(fā)。

二、SQLAlchemy使用

SQLAlchemy根據(jù)模型查詢(xún)

  1. 引入和初始化
    導(dǎo)入sqlalchemy模塊,然后使用create_engine創(chuàng)建引擎,sessionmaker創(chuàng)建會(huì)話(huà)類(lèi)并生成會(huì)話(huà)對(duì)象。
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker

engine = create_engine(SQLALCHEMY_DATABASE_URI)
db_session = scoped_session(sessionmaker(autoflush=False,bind=engine))
  1. 使用sql 或者 數(shù)據(jù)模型

這里先舉例模型方式:
在SQLAlchemy中,declarative_base()用來(lái)創(chuàng)建一個(gè)基類(lèi),這個(gè)基類(lèi)會(huì)為所有繼承它的子類(lèi)提供declarative的ORM功能。
TblObject = declarative_base() 的作用是:
3. 創(chuàng)建了一個(gè)名為T(mén)blObject的基類(lèi)
4. 這個(gè)TblObject具有declarative的功能
5. 后續(xù)定義的模型類(lèi)可以繼承這個(gè)TblObject基類(lèi)來(lái)使用declarative

from sqlalchemy.orm import declarative_base
from sqlalchemy import Column, Text, Integer,String, VARCHAR, TIMESTAMP, BOOLEAN, Float, text

TblObject = declarative_base() 

class User(TblObject):
	__tablename__ = 'table_user'
	__table_args__ = ({"schema": "public"})
	id = Column(Integer, primary_key=True)
	name = Column(String)

query = db_session.query(User)
user = query.first() 
print(user.name)

SQLAlchemy SQL 格式化的方式

  1. 將sql語(yǔ)句本身不包含參數(shù)格式化,直接作為文本構(gòu)建完整的sql:
    要想實(shí)現(xiàn)變量替換,需要使用f-string的格式
myschema = 'xxxx'
sql = text(f'SELECT id FROM {myschema }.table...') 

注意看字符串前面有個(gè)f。

  1. 使用參數(shù)綁定的方式,而不是%格式化:
sql = text('SELECT id FROM :schema.table...')
params = {'schema': 'my_schema'}
result = session.execute(sql, params)

總結(jié):

  1. sql文本內(nèi)不要再使用% formatting
  2. 使用f-string或參數(shù)綁定格式化
  3. 創(chuàng)建text對(duì)象時(shí)直接構(gòu)建完整sql文本

參數(shù)綁定也可以提高安全性,避免SQL注入\

db_session.query和 db_session.execute區(qū)別

在SQLAlchemy中,db_session.query()和db_session.execute()主要有以下幾點(diǎn)區(qū)別:

  1. 返回值不同:
    • db_session.query() 返回一個(gè)Query對(duì)象,可以用于構(gòu)建查詢(xún)并最終獲取結(jié)果。
    • db_session.execute() 直接執(zhí)行語(yǔ)句并返回結(jié)果。
  2. 查詢(xún)方式不同:
    • db_session.query() 通過(guò)ORM構(gòu)建查詢(xún)。
    • db_session.execute() 通過(guò)原生SQL語(yǔ)句查詢(xún)。
  3. 查詢(xún)靈活性不同:
    • db_session.query() 可以構(gòu)建非常靈活的查詢(xún),包含各種過(guò)濾、JOIN等。
    • db_session.execute() 只能執(zhí)行簡(jiǎn)單的SQL語(yǔ)句查詢(xún)。
  4. 返回結(jié)果不同:
    • db_session.query() 返回的是ORM對(duì)象或者自定義類(lèi)的實(shí)例。
    • db_session.execute() 直接返回行數(shù)據(jù)組成的列表。
  5. 性能不同:
    • 對(duì)簡(jiǎn)單查詢(xún),db_session.execute()往往更快。
    • 對(duì)復(fù)雜查詢(xún),db_session.query()可以通過(guò)ORM特性進(jìn)行優(yōu)化。
      所以,簡(jiǎn)單來(lái)說(shuō):
  • db_session.query() 是面向?qū)ο蟮牟樵?xún)方式,更靈活,但復(fù)雜查詢(xún)可能有性能問(wèn)題。
  • db_session.execute() 是執(zhí)行原生SQL的直接查詢(xún),性能好但不夠靈活。

需要特別注意的點(diǎn):使用 db_session.query() 后獲取的 ORM 對(duì)象實(shí)例,在訪(fǎng)問(wèn)其屬性之前,需要確保與該查詢(xún)關(guān)聯(lián)的 db_session 沒(méi)有關(guān)閉或失效。

否則報(bào)錯(cuò):

raise orm_exc.DetachedInstanceError(
sqlalchemy.orm.exc.DetachedInstanceError: Instance <User at 0x7f2973d6fbe0> is not bound to a Session; attribute refresh operation cannot proceed (Background on this error at: https://sqlalche.me/e/20/bhk3)

通常的使用模式是:

db_session = Session() 

# 創(chuàng)建查詢(xún)
query = db_session.query(User)

# 獲取用戶(hù)對(duì)象
user = query.first() 

# 訪(fǎng)問(wèn)屬性
print(user.name)

# 關(guān)閉會(huì)話(huà)
db_session.close()

在關(guān)閉 db_session 之前,需要先完成對(duì)其查詢(xún)結(jié)果的處理和訪(fǎng)問(wèn)。
如果在獲取到 user 對(duì)象后立即關(guān)閉會(huì)話(huà),然后訪(fǎng)問(wèn) user.name,會(huì)發(fā)生 detached實(shí)例錯(cuò)誤。
因?yàn)樵跁?huì)話(huà)關(guān)閉后,user 對(duì)象脫離了會(huì)話(huà),屬性無(wú)法加載。

使用 db_session.execute() 執(zhí)行原生SQL查詢(xún)general不會(huì)存在會(huì)話(huà)過(guò)早關(guān)閉導(dǎo)致屬性訪(fǎng)問(wèn)錯(cuò)誤的問(wèn)題。
db_session.execute() 返回的是數(shù)據(jù)庫(kù)行記錄組成的結(jié)果集,不涉及 ORM 對(duì)象映射。

實(shí)測(cè)demo 總結(jié):讓我們留意一下SQLAlchemy 的 lazy loading 特性

python常用庫(kù)之?dāng)?shù)據(jù)庫(kù)orm框架之SQLAlchemy,Python,數(shù)據(jù)庫(kù),python,開(kāi)發(fā)語(yǔ)言
python常用庫(kù)之?dāng)?shù)據(jù)庫(kù)orm框架之SQLAlchemy,Python,數(shù)據(jù)庫(kù),python,開(kāi)發(fā)語(yǔ)言
測(cè)試結(jié)果:經(jīng)過(guò)測(cè)試,query = db_session.query(User).all() 這樣db_session.close() 后,使用query[0].name會(huì)報(bào)錯(cuò),但是query = db_session.query(User),close之后 query的數(shù)據(jù)還能用。

db_session.query(User) 只是構(gòu)造了一個(gè)查詢(xún),并沒(méi)有立即獲取結(jié)果。
而 db_session.query(User).all() 執(zhí)行了查詢(xún)并獲取了結(jié)果。
在會(huì)話(huà)關(guān)閉后,這兩種情況的行為不同:

  1. 對(duì)于僅構(gòu)造查詢(xún)的 db_session.query(User),由于沒(méi)有結(jié)果產(chǎn)生,所以不會(huì)有 detached 實(shí)例的問(wèn)題。我們可以在會(huì)話(huà)關(guān)閉后,使用這個(gè)查詢(xún)加上過(guò)濾條件等再次執(zhí)行,產(chǎn)生新結(jié)果。
  2. 但對(duì)于立即執(zhí)行了的 db_session.query(User).all(),其結(jié)果中的實(shí)例與關(guān)閉后的會(huì)話(huà)失去關(guān)聯(lián),成為 detached 實(shí)例,會(huì)導(dǎo)致訪(fǎng)問(wèn)屬性失敗。

這與 SQLAlchemy 的 lazy loading 特性有關(guān) - 查詢(xún)只有在需要時(shí)才執(zhí)行和加載實(shí)例。

  • 構(gòu)造查詢(xún)只生成了一個(gè)執(zhí)行計(jì)劃,不涉及具體實(shí)例數(shù)據(jù),所以會(huì)話(huà)關(guān)閉后計(jì)劃還可以再執(zhí)行。
  • 但執(zhí)行查詢(xún)并獲取實(shí)例,實(shí)際上已經(jīng)加載了具體的數(shù)據(jù),所以會(huì)依賴(lài)會(huì)話(huà)提供的數(shù)據(jù)狀態(tài)。

scoped session

使用 db_session.query() 時(shí),為了避免訪(fǎng)問(wèn) detached 實(shí)例,我們希望延遲關(guān)閉會(huì)話(huà) db_session。但這樣就無(wú)法及時(shí)提交事務(wù),可能會(huì)導(dǎo)致鎖表問(wèn)題。

解決方法:

  1. 在查詢(xún)之后、訪(fǎng)問(wèn)實(shí)例屬性之前,先顯式提交事務(wù):
db_session.query(...)

db_session.commit() # 提交事務(wù)

obj.some_attr # 訪(fǎng)問(wèn)屬性

這可以先釋放鎖,同時(shí)實(shí)例也綁定到會(huì)話(huà)中。

  1. 使用scoped session,可以避免手動(dòng) close db_session。
from sqlalchemy.orm import sessionmaker, scoped_session

session_factory = sessionmaker(bind=engine)
Session = scoped_session(session_factory)

def get_user():
    session = Session()
    return session.query(User).first()

這里的Session是一個(gè)scoped session類(lèi)。其特點(diǎn)是:

  1. 每個(gè)線(xiàn)程或請(qǐng)求都會(huì)自動(dòng)創(chuàng)建一個(gè)新的session實(shí)例,避免同一個(gè)session跨線(xiàn)程/請(qǐng)求使用。
  2. 使用完session后不需要關(guān)閉它,scoped session會(huì)在當(dāng)前上下文退出后自動(dòng)關(guān)閉、invalidate該session。
  3. 所以我們只需要使用Session類(lèi)創(chuàng)建session,不需要close。
  4. 不同的框架可以集成scoped session到自己的上下文。比如Flask集成后,每個(gè)請(qǐng)求都會(huì)自動(dòng)開(kāi)啟一個(gè)session,請(qǐng)求結(jié)束后自動(dòng)關(guān)閉。
  5. 這樣就可以不需要我們手動(dòng)管理session的生命周期。

所以綜上,scoped session通過(guò)封裝context管理,讓session的生命周期與當(dāng)前上下文(線(xiàn)程、請(qǐng)求等)綁定,自動(dòng)開(kāi)啟和關(guān)閉,省去了手動(dòng)管理的問(wèn)題。

總結(jié):
方法1: 我們只調(diào)commmit,這里不調(diào)colse(),需要其他地方,只有在確定不用的情況下才調(diào)close。
方法2:我們使用scoped_session,scoped session 的生命周期由應(yīng)用管理,不需要我們手動(dòng)關(guān)閉。

使用scoped_session,這個(gè) session 實(shí)例綁定到線(xiàn)程/請(qǐng)求,在其線(xiàn)程結(jié)束時(shí)自動(dòng)關(guān)閉.

關(guān)于scoped_session自動(dòng)提交事務(wù)

scoped_session 的工作原理是:

  • 為每個(gè)線(xiàn)程或請(qǐng)求創(chuàng)建一個(gè)新的 session 實(shí)例
  • 這個(gè) session 實(shí)例綁定到線(xiàn)程/請(qǐng)求,在其結(jié)束時(shí)自動(dòng)關(guān)閉
  • 開(kāi)發(fā)者只需要使用 Session 類(lèi)即可,不需要手動(dòng)關(guān)閉
    也就是說(shuō),每個(gè)線(xiàn)程/請(qǐng)求都會(huì)有一個(gè)獨(dú)立的 session 實(shí)例,這個(gè)實(shí)例不會(huì)自動(dòng)提交。

如果我們需要自動(dòng)提交,需要在使用 session 的時(shí)候設(shè)置:

在會(huì)話(huà)層面設(shè)置自動(dòng)提交:

from sqlalchemy.orm import sessionmaker

Session = sessionmaker(bind=engine)
session = Session()

session.autocommit = True

通過(guò)設(shè)置session.autocommit啟用自動(dòng)提交。這會(huì)針對(duì)當(dāng)前線(xiàn)程的 session 實(shí)例開(kāi)啟自動(dòng)提交。

另外,scoped_session 也不建議使用自動(dòng)提交模式,因?yàn)闀?huì)有并發(fā)問(wèn)題。推薦的方式還是手動(dòng)提交控制事務(wù)。

總結(jié),對(duì)于 scoped_session:

  • 在創(chuàng)建時(shí)設(shè)置autocommit 不會(huì)生效
  • 應(yīng)在使用時(shí)針對(duì) session 實(shí)例設(shè)置autocommit
  • 推薦的方式仍是手動(dòng)提交控制事務(wù)

參數(shù)autoflush=False 的工作機(jī)制

db_session = scoped_session(sessionmaker(autoflush=False, bind=engine))
db_session = scoped_session(sessionmaker(bind=engine)) 

如上,有什么區(qū)別?

關(guān)閉自動(dòng) flush(autoflush=False)的主要目的是可以更精細(xì)地控制 flush 的時(shí)機(jī),原因如下:

  1. 自動(dòng) flush 可能導(dǎo)致不必要的數(shù)據(jù)庫(kù)寫(xiě)入操作,比如在一個(gè)事務(wù)中有多次 CRUD 操作時(shí),希望只在事務(wù)提交時(shí)一次性寫(xiě)入,而不是每次操作都觸發(fā) flush。
  2. 在一些場(chǎng)景下需要確保 flush 只在事務(wù)提交時(shí)發(fā)生,如兩個(gè)關(guān)聯(lián)對(duì)象的變更,希望它們的變更作為一個(gè)事務(wù)執(zhí)行。
  3. 需要根據(jù)業(yè)務(wù)邏輯精確控制 flush 時(shí)機(jī),而不是通過(guò)隱式的自動(dòng) flush。

SQLAlchemy中的session.commit()內(nèi)部會(huì)自動(dòng)調(diào)用session.flush()來(lái)保證所有pending的變更都被持久化。
即使設(shè)置autoflush=False,commit操作也會(huì)強(qiáng)制執(zhí)行flush。只是在commit之外的其他情況下,需要手動(dòng)調(diào)用flush。

autoflush=False的情況下:

  • 正常的增刪改操作不會(huì)自動(dòng)flush
  • 調(diào)用commit會(huì)觸發(fā)強(qiáng)制flush以持久化變更
    這是SQLAlchemy的一種保護(hù)機(jī)制,來(lái)確保在事務(wù)提交時(shí)不會(huì)丟失還未flush的變更。

autoflush=False 需要手動(dòng)flush,但不影響commit的自動(dòng)flush行為。

三、關(guān)于SQLAlchemy自動(dòng)提交事務(wù)

背景:
工作發(fā)現(xiàn)使用,出現(xiàn)很多 sqlalchemy出現(xiàn)很多未提交事務(wù) 情況。

demo:

from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy import text


username="aaa"
password="xxx"
host="127.0.0.1"
port="5432"
db="xx"
sqlalchemy_uri = f"postgresql://{username}:{password}@{host}:{port}/{db}"

engine = create_engine(sqlalchemy_uri)

#engine = create_engine(sqlalchemy_uri, echo=False, client_encoding='utf8', pool_size=100, pool_recycle=3600)
db_session = scoped_session(sessionmaker(bind=engine))
										 								 
sql = text('SELECT * FROM auth_user WHERE id = :userid;')
userid=1

#  execute() 方法僅僅是執(zhí)行查詢(xún),不會(huì)自動(dòng)提交事務(wù)。
objs = db_session.execute(sql, {"userid": userid}).fetchall()
print(objs)

**每個(gè)session默認(rèn)都是在一個(gè)事務(wù)中,不會(huì)自動(dòng)提交。**因此當(dāng)你調(diào)用db_session.execute(sql)時(shí),會(huì)默認(rèn)復(fù)用當(dāng)前session的事務(wù)來(lái)執(zhí)行,而這個(gè)session已經(jīng)在一個(gè)未提交的事務(wù)中了。

這與直接調(diào)用begin()開(kāi)始一個(gè)新事務(wù)其實(shí)效果是一樣的。

PostgreSQL 和 MySQL 自動(dòng)提交區(qū)別

PostgreSQL 的默認(rèn)設(shè)置是自動(dòng)提交關(guān)閉的,每次事務(wù)需要顯式地通過(guò) COMMIT 提交。

PostgreSQL的事務(wù)autocommit是transaction級(jí)的。每個(gè)transaction需要顯式提交或回滾。
在PostgreSQL中,autocommit是作用于每個(gè)事務(wù)(transaction)的,主要體現(xiàn)在以下兩個(gè)方面:

  1. 新建立的連接默認(rèn)都是非自動(dòng)提交狀態(tài)(autocommit=off)。這個(gè)連接下的所有事務(wù)操作默認(rèn)都是非自動(dòng)提交的。
  2. 開(kāi)始一個(gè)新的事務(wù)時(shí),這個(gè)事務(wù)會(huì)繼承連接當(dāng)前的autocommit狀態(tài)。如果連接是非自動(dòng)提交的,那么這個(gè)事務(wù)也是非自動(dòng)提交的。

舉個(gè)例子:
– 新建立連接,默認(rèn)autocommit=off

postgres=# begin; -- 開(kāi)始一個(gè)新事務(wù),繼承連接的autocommit=off

postgres=# insert into table_a values (1); -- 非自動(dòng)提交

postgres=# commit; -- 需要顯式提交事務(wù)

新連接默認(rèn)的是非自動(dòng)提交狀態(tài)。當(dāng)開(kāi)始一個(gè)新的事務(wù)時(shí),這個(gè)事務(wù)繼承了連接的非自動(dòng)提交屬性。所以我們必須通過(guò)提交事務(wù)來(lái)持久化改變。

  • MySQL 的默認(rèn)設(shè)置是自動(dòng)提交開(kāi)啟的,每條語(yǔ)句會(huì)自動(dòng)提交事務(wù)。
    MySQL的事務(wù)autocommit標(biāo)志是session級(jí)的。也就是說(shuō),一個(gè)會(huì)話(huà)內(nèi)全部操作默認(rèn)都是自動(dòng)提交的。

您的問(wèn)題提到了MySQL中的自動(dòng)提交模式,這和PostgreSQL中的事務(wù)處理模式有些不同。
MySQL中的自動(dòng)提交(autocommit)是作用于整個(gè)數(shù)據(jù)庫(kù)連接會(huì)話(huà)的,主要體現(xiàn)在:

  1. 新建立的連接默認(rèn)是自動(dòng)提交模式(autocommit=on)。
  2. 連接的自動(dòng)提交模式作用于該連接下執(zhí)行的所有事務(wù)。不管執(zhí)行多少個(gè)事務(wù),都使用該連接的自動(dòng)提交模式。
  3. 設(shè)置自動(dòng)提交模式會(huì)改變連接的默認(rèn)提交行為。

舉個(gè)例子:
– 新連接默認(rèn)autocommit=ON

mysql> start transaction; -- 開(kāi)始事務(wù),但繼承連接的自動(dòng)提交模式

mysql> insert into table_a values (1); -- 自動(dòng)提交

mysql> commit; -- 提交無(wú)實(shí)際效果,因?yàn)橐炎詣?dòng)提交

在這個(gè)例子中,由于連接的默認(rèn)autocommit=on,所以不管執(zhí)行多少個(gè)事務(wù),每條SQL語(yǔ)句都會(huì)隱式提交。

SQLAlchemy 的設(shè)計(jì)是為了最大程度兼容不同數(shù)據(jù)庫(kù)的行為,所以從 1.4 版本開(kāi)始采用關(guān)閉自動(dòng)提交作為默認(rèn)值,這更符合 PostgreSQL 和一些其他數(shù)據(jù)庫(kù)的行為。

總結(jié):PostgreSQL的autocommit屬性是針對(duì)每個(gè)事務(wù)的,而不是整個(gè)會(huì)話(huà)。這就要求我們必須顯式地提交或回滾事務(wù)來(lái)結(jié)束一個(gè)事務(wù)。

查看PostgreSQL當(dāng)前連接是否開(kāi)啟自動(dòng)提交

查詢(xún) pg_settings 系統(tǒng)表:

SELECT setting FROM pg_settings WHERE name = 'default_transaction_isolation'; 

返回 ‘read committed’ 表示未開(kāi)啟。

是否可以直接查詢(xún)PostgreSQL的autocommit狀態(tài),而不通過(guò) default_transaction_isolation 這種間接的方式。
直接查詢(xún)autocommit的參數(shù)在PostgreSQL中是不支持的。因?yàn)閍utocommit實(shí)際上不是一個(gè)配置參數(shù),而是個(gè)概念,是由default_transaction_isolation參數(shù)決定的。

沒(méi)有辦法直接用SHOW或者SELECT方式獲取autocommit的狀態(tài)。
之所以我們常用 default_transaction_isolation 來(lái)判斷,是因?yàn)檫@兩個(gè)設(shè)置在PostgreSQL內(nèi)部是耦合的:

  • read committed 表示關(guān)閉了autocommit
  • read uncommitted 表示開(kāi)啟了autocommit
    所以default_transaction_isolation等于read committed的時(shí)候,就可以確定autocommit是關(guān)閉的。

四、工作遇到的問(wèn)題

1. pg報(bào)錯(cuò):unexpected EOF on client connection

在 PostgreSQL 中,“unexpected EOF on client connection” 這個(gè)錯(cuò)誤通常表示客戶(hù)端應(yīng)用程序異常中斷了與數(shù)據(jù)庫(kù)的連接,導(dǎo)致有一個(gè)未完成的打開(kāi)事務(wù)狀態(tài)。
這種錯(cuò)誤的常見(jiàn)原因包括:

  1. 應(yīng)用程序進(jìn)程崩潰或異常退出,沒(méi)有正常關(guān)閉數(shù)據(jù)庫(kù)連接。
  2. 網(wǎng)絡(luò)連接異常中斷。比如網(wǎng)絡(luò)閃斷,客戶(hù)端機(jī)器宕機(jī)等。
  3. 客戶(hù)端沒(méi)有正確處理查詢(xún)超時(shí)或者服務(wù)器重啟的情況。
  4. 由于編程錯(cuò)誤或者資源問(wèn)題,客戶(hù)端忘記提交/回滾一個(gè)長(zhǎng)時(shí)間運(yùn)行的事務(wù)。
  5. 數(shù)據(jù)庫(kù)連接泄露,占用了所有可用連接。

當(dāng)出現(xiàn)這個(gè)錯(cuò)誤時(shí),該未提交的事務(wù)會(huì)一直持有鎖占用連接,阻塞其他事務(wù),因此需要進(jìn)行以下處理:

  1. 檢查網(wǎng)絡(luò)鏈接情況,確保客戶(hù)端和數(shù)據(jù)庫(kù)服務(wù)器網(wǎng)絡(luò)暢通。
  2. 檢查客戶(hù)端應(yīng)用程序代碼,確保正確處理超時(shí)、事務(wù)提交等情況。
  3. 在數(shù)據(jù)庫(kù)端執(zhí)行以下命令,手動(dòng)終止該占用連接的事務(wù):
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE state = 'idle in transaction'; 

你執(zhí)行這個(gè)語(yǔ)句后,處在 idle in transaction 狀態(tài)的后端進(jìn)程將被強(qiáng)制終止,相關(guān)的事務(wù)也會(huì)被回滾。
注:pg_terminate_backend() 函數(shù)的返回值 ‘t’ 表示終止后端成功。

終止后端進(jìn)程后,還需要幾個(gè)后續(xù)步驟:

  1. 再次執(zhí)行同樣的查詢(xún),檢查是否還有處在 idle in transaction 狀態(tài)的進(jìn)程:
SELECT * FROM pg_stat_activity WHERE state = 'idle in transaction';
  1. 分析日志,找到未提交事務(wù)的根本原因,比如編程錯(cuò)誤、資源問(wèn)題等,從代碼級(jí)別解決問(wèn)題。
  2. 合理配置數(shù)據(jù)庫(kù)連接池,避免連接泄露。
  3. 調(diào)整數(shù)據(jù)庫(kù)配置,適當(dāng)增大max_connections數(shù)值。

2. 報(bào)錯(cuò):sqlalchemy.exc.ArgumentError: autocommit=True is no longer supported

早期版本的 SQLAlchemy 支持在 Engine 創(chuàng)建時(shí)設(shè)置 autocommit=True,將該引擎設(shè)置為自動(dòng)提交事務(wù)模式。但是從版本 1.4 開(kāi)始,這個(gè)參數(shù)就不再支持了。

導(dǎo)致這個(gè)錯(cuò)誤的典型代碼如:

engine = create_engine(URL, autocommit=True)

要修復(fù)這個(gè)錯(cuò)誤,需要移除 autocommit 參數(shù),改為手動(dòng)管理事務(wù):

  1. 去掉 autocommit=True
engine = create_engine(URL) 
  1. 在代碼中手動(dòng)提交事務(wù):
with engine.begin() as conn:
    conn.execute(...) 
    conn.commit()
  1. 或者開(kāi)啟自動(dòng)提交模式:
connection = engine.connect()
connection.autocommit = True

總之,Engine 對(duì)象不再支持 autocommit 參數(shù)。需要通過(guò)上述方式自行控制事務(wù)提交。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-727293.html

到了這里,關(guān)于python常用庫(kù)之?dāng)?shù)據(jù)庫(kù)orm框架之SQLAlchemy的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀(guān)點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【1 beego學(xué)習(xí) -MAC框架與ORM數(shù)據(jù)庫(kù)】

    【1 beego學(xué)習(xí) -MAC框架與ORM數(shù)據(jù)庫(kù)】

    1,由于在github上安裝,所以需要安裝git軟件,安裝過(guò)程一直點(diǎn)擊下一步即可。安裝完成后需要配置環(huán)境變量 修改go環(huán)境變量 go env -w GO111MODULE=on go env -w GOPROXY=https://goproxy.cn 2,設(shè)置GOPATH 環(huán)境變量,并且將 GOPATH/bin 加入到了環(huán)境變量。 3,安裝bee go get -u -v github.com/astaxie/beego go get

    2024年02月11日
    瀏覽(19)
  • Java與數(shù)據(jù)庫(kù):JDBC和ORM框架的使用和效率優(yōu)化

    Java與數(shù)據(jù)庫(kù):JDBC和ORM框架的使用和效率優(yōu)化

    ? 隨著互聯(lián)網(wǎng)的快速發(fā)展和大數(shù)據(jù)時(shí)代的到來(lái),數(shù)據(jù)庫(kù)在軟件開(kāi)發(fā)中起到了至關(guān)重要的作用。Java作為一門(mén)強(qiáng)大而廣泛應(yīng)用的編程語(yǔ)言,提供了多種與數(shù)據(jù)庫(kù)交互的方式。其中,JDBC和ORM框架是最常用的兩種方式。本文將深入探討JDBC和ORM框架的使用方法,并分享一些提高效率的

    2024年02月08日
    瀏覽(53)
  • 獻(xiàn)給轉(zhuǎn)java的c#和java程序員的數(shù)據(jù)庫(kù)orm框架

    一個(gè)好的程序員不應(yīng)被語(yǔ)言所束縛,正如我現(xiàn)在開(kāi)源java的orm框架一樣,如果您是一位轉(zhuǎn)java的c#程序員,那么這個(gè)框架可以帶給你起碼沒(méi)有那么差的業(yè)務(wù)編寫(xiě)和強(qiáng)類(lèi)型體驗(yàn)。如果您是一位java程序員,那么該框架可以提供比 Mybatis-Plus 功能更加豐富、性能更高,更加輕量和完全免費(fèi)的體

    2024年02月05日
    瀏覽(18)
  • 【Python】sqlmodel: Python 數(shù)據(jù)庫(kù)管理ORM 的終極形態(tài)?

    大家都知道ORM(Object Relational Mapping)是一種將對(duì)象和關(guān)系數(shù)據(jù)庫(kù)中的表進(jìn)行映射的技術(shù),它可以讓開(kāi)發(fā)者更加方便地操作數(shù)據(jù)庫(kù),而不用直接使用SQL語(yǔ)句。 直接使用SQL語(yǔ)句操作數(shù)據(jù)庫(kù),雖然可以讓開(kāi)發(fā)者直接與數(shù)據(jù)庫(kù)打交道,但手動(dòng)編寫(xiě)SQL語(yǔ)句,容易出錯(cuò),而且靈活性上比

    2024年02月08日
    瀏覽(16)
  • Django ORM:數(shù)據(jù)庫(kù)操作的Python化藝術(shù)

    Django ORM:數(shù)據(jù)庫(kù)操作的Python化藝術(shù)

    Django的對(duì)象關(guān)系映射器(ORM)是其核心功能之一,允許開(kāi)發(fā)者使用Python代碼來(lái)定義、操作和查詢(xún)數(shù)據(jù)庫(kù)。這篇文章將帶你深入了解Django ORM的強(qiáng)大之處,從基本概念到高級(jí)查詢(xún)技巧,提供豐富的示例幫助你掌握使用Django ORM進(jìn)行有效和高效的數(shù)據(jù)庫(kù)操作。 Django ORM的目的是提供一

    2024年02月04日
    瀏覽(33)
  • Android之 常用數(shù)據(jù)庫(kù)框架整理

    Android之 常用數(shù)據(jù)庫(kù)框架整理

    一 簡(jiǎn)介 1.1 上節(jié)說(shuō)了關(guān)系型數(shù)據(jù)庫(kù)有以下幾種: Oracle、Microsoft SQL Server、Microsoft Access、MySQL、SQLite 1.2 各自的領(lǐng)域也不一樣 java,C#,php等用Oracle,Microsoft SQL Server,MySQL比較多。 移動(dòng)端Android,IOS等用SQLite比較多 1.3?SQLite是一種輕量型數(shù)據(jù)庫(kù),有以下優(yōu)點(diǎn): 不需要一個(gè)單獨(dú)的服

    2024年02月14日
    瀏覽(16)
  • Django ORM:最全面的數(shù)據(jù)庫(kù)處理指南

    深度探討Django ORM的概念、基礎(chǔ)使用、進(jìn)階操作以及詳細(xì)解析在實(shí)際使用中如何處理數(shù)據(jù)庫(kù)操作。同時(shí),我們還討論了模型深入理解,如何進(jìn)行CRUD操作,并且深化理解到數(shù)據(jù)庫(kù)遷移等高級(jí)主題。為了全面解讀Django ORM,我們也討論了其存在的不足,并對(duì)其未來(lái)發(fā)展進(jìn)行了展望。

    2024年02月13日
    瀏覽(25)
  • SQLAlchemy ORM指南:簡(jiǎn)化數(shù)據(jù)庫(kù)操作的最佳實(shí)踐

    SQLAlchemy ORM指南:簡(jiǎn)化數(shù)據(jù)庫(kù)操作的最佳實(shí)踐

    背景: ? SQLAlchemy是一個(gè)數(shù)據(jù)庫(kù)的ORM框架,讓我們操作數(shù)據(jù)庫(kù)的時(shí)候不要再用SQL語(yǔ)句了,跟直接操作模型一樣。操作十分便捷,其實(shí)SQLAlchemy應(yīng)該是在Flask和Django應(yīng)用的特別多,而且在flask中已經(jīng)集成了flask_sqlalchemy ,好像是 SQLAlchemy的作者和 Flask是同一個(gè),背景了解到這里就可

    2024年01月20日
    瀏覽(57)
  • Django創(chuàng)建應(yīng)用、ORM的進(jìn)階使用及模型類(lèi)數(shù)據(jù)庫(kù)遷移

    Django創(chuàng)建應(yīng)用、ORM的進(jìn)階使用及模型類(lèi)數(shù)據(jù)庫(kù)遷移

    Django 項(xiàng)目就是基于 Django 框架開(kāi)發(fā)的 Web 應(yīng)用,它包含了一組配置和多個(gè)應(yīng)用,我們把應(yīng)用稱(chēng)之為 App,在前文中對(duì)它也做了相應(yīng)的介紹,比如 auth、admin,它們都屬于 APP。 一個(gè) App 就是一個(gè) Python 包,通常一個(gè) App 可以包含模型、視圖、模板和 URL 配置文件,可以被應(yīng)用到多個(gè)

    2024年02月09日
    瀏覽(94)
  • Django學(xué)習(xí)記錄:使用ORM操作MySQL數(shù)據(jù)庫(kù)并完成數(shù)據(jù)的增刪改查

    Django學(xué)習(xí)記錄:使用ORM操作MySQL數(shù)據(jù)庫(kù)并完成數(shù)據(jù)的增刪改查

    數(shù)據(jù)庫(kù)操作 MySQL數(shù)據(jù)庫(kù)+pymysql Django開(kāi)發(fā)操作數(shù)據(jù)庫(kù)更簡(jiǎn)單,內(nèi)部提供了ORM框架。 安裝第三方模塊 ORM可以做的事: 1、創(chuàng)建、修改、刪除數(shù)據(jù)庫(kù)中的表(不用寫(xiě)SQL語(yǔ)句)?!緹o(wú)法創(chuàng)建數(shù)據(jù)庫(kù)】 2、操作表中的數(shù)據(jù)(不用寫(xiě)SQL語(yǔ)句)。 1、自己創(chuàng)建數(shù)據(jù)庫(kù) 1)啟動(dòng)MySQL服務(wù) 2)自帶

    2024年02月14日
    瀏覽(96)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包