最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python操作MySQL數(shù)據(jù)庫(kù)時(shí)常見(jiàn)的三個(gè)陷阱及解決方法

 更新時(shí)間:2026年05月31日 08:29:45   作者:detayun  
這段文章詳細(xì)剖析了pymysql、mysql-connector-python及SQLAlchemy在數(shù)據(jù)庫(kù)操作中可能遇到的三個(gè)關(guān)鍵問(wèn)題:異常處理不當(dāng)導(dǎo)致數(shù)據(jù)不一致、連接池管理不當(dāng)引發(fā)資源耗盡、以及批量更新操作時(shí)事件監(jiān)聽(tīng)失效,需要的朋友可以參考下

坑一:pymysql —— 異常吞掉,錢(qián)扣了沒(méi)到賬

案發(fā)現(xiàn)場(chǎng)

import pymysql

conn = pymysql.connect(host='localhost', user='root', password='pwd', database='test')
cursor = conn.cursor()

# 轉(zhuǎn)賬:扣款
cursor.execute("UPDATE accounts SET balance = balance - 100 WHERE id = 1")
# 假設(shè)這里程序崩潰 / 網(wǎng)絡(luò)超時(shí) / 拋出異常...
# 加款永遠(yuǎn)沒(méi)執(zhí)行
cursor.execute("UPDATE accounts SET balance = balance + 100 WHERE id = 2")

conn.commit()  # 第一條已經(jīng)生效,無(wú)法回滾

結(jié)果:用戶(hù)A被扣了100塊,用戶(hù)B沒(méi)收到錢(qián)。數(shù)據(jù)不一致,且無(wú)法挽回。

根因

pymysql 默認(rèn) autocommit=False,但每條 execute 本身不會(huì)自動(dòng)提交——問(wèn)題出在異常發(fā)生后,第一條 SQL 已經(jīng)被 MySQL 隱式提交(因?yàn)?pymysql 在某些異常場(chǎng)景下會(huì)觸發(fā)自動(dòng)提交),或者更常見(jiàn)的情況是:開(kāi)發(fā)者以為異常會(huì)自動(dòng)回滾,但實(shí)際上沒(méi)有顯式調(diào)用 rollback()。

解決方法

try:
    cursor.execute("UPDATE accounts SET balance = balance - 100 WHERE id = 1")
    cursor.execute("UPDATE accounts SET balance = balance + 100 WHERE id = 2")
    conn.commit()
except Exception as e:
    conn.rollback()  # ← 必須顯式回滾
    raise  # 或記錄日志后重新拋出
finally:
    cursor.close()
    conn.close()

關(guān)鍵原則try 里寫(xiě)業(yè)務(wù) SQL,except 里必須有 rollback(),finally 里關(guān)閉連接。三件套缺一不可。

坑二:mysql-connector-python —— 連接池泄漏,服務(wù)跑著跑著就掛了

案發(fā)現(xiàn)場(chǎng)

import mysql.connector
from mysql.connector import pooling

dbconfig = {
    "host": "localhost", "user": "root", "password": "pwd", "database": "test"
}
connection_pool = pooling.MySQLConnectionPool(pool_name="mypool", pool_size=5, **dbconfig)

def get_user(user_id):
    conn = connection_pool.get_connection()  # 從池中取連接
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
    result = cursor.fetchall()
    # 忘記關(guān)閉連接,直接返回
    return result

結(jié)果:前5次請(qǐng)求正常,第6次開(kāi)始報(bào)錯(cuò) Too many connections。因?yàn)檫B接取走后沒(méi)歸還,池子里的5個(gè)連接被永久占用。

根因

mysql-connector-python 的連接池行為是連接常駐——取走后不會(huì)自動(dòng)回收。與 SQLAlchemy 的 QueuePool(空閑超時(shí)后銷(xiāo)毀連接)不同,這里的連接一旦泄漏,池子容量就永久減少,直到耗盡。

解決方法

def get_user(user_id):
    conn = connection_pool.get_connection()
    try:
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
        return cursor.fetchall()
    finally:
        cursor.close()
        conn.close()  # ← 必須歸還連接到池中

或者用上下文管理器:

from contextlib import closing

def get_user(user_id):
    with closing(connection_pool.get_connection()) as conn:
        with conn.cursor() as cursor:
            cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
            return cursor.fetchall()
    # 退出 with 自動(dòng)關(guān)閉,連接歸還池中

監(jiān)控指標(biāo):定期執(zhí)行 SHOW PROCESSLIST,觀察 Sleep 狀態(tài)的連接數(shù)是否持續(xù)增長(zhǎng)。

坑三:SQLAlchemy —— 批量更新時(shí),事件監(jiān)聽(tīng)器"沉默"了

案發(fā)現(xiàn)場(chǎng)

from sqlalchemy import event, update
from sqlalchemy.orm import Session

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String(50))
    updated_at = Column(DateTime)

# 定義事件:每次更新自動(dòng)維護(hù) updated_at
@event.listens_for(User, 'before_update')
def set_updated_at(mapper, connection, target):
    target.updated_at = datetime.now()

# 業(yè)務(wù)代碼:批量更新用戶(hù)狀態(tài)
session = Session()
stmt = update(User).where(User.status == 'pending').values(status='processed')
session.execute(stmt)  # ← 監(jiān)聽(tīng)器根本沒(méi)觸發(fā)
session.commit()

結(jié)果:1000條記錄的 status 改了,但 updated_at 全是 NULL。因?yàn)?session.execute(stmt) 走的是 Core 層,繞過(guò)了 ORM 的對(duì)象生命周期,事件監(jiān)聽(tīng)器根本不知道發(fā)生了更新。

根因

SQLAlchemy 的事件系統(tǒng)綁定的是 ORM 對(duì)象的狀態(tài)變化session.execute(update(...)) 是直接執(zhí)行 SQL,不經(jīng)過(guò) ORM 對(duì)象加載,所以 before_update / after_update 全部靜默。

解決方法(三選一)

方案適用場(chǎng)景代碼
回歸 ORM 遍歷更新數(shù)據(jù)量 < 1萬(wàn)for u in session.query(User).filter_by(status='pending'): u.status='processed'
SQL 里直接寫(xiě)追求性能values(status='processed', updated_at=func.now())
數(shù)據(jù)庫(kù)觸發(fā)器強(qiáng)一致性要求交給 MySQL 層,ON UPDATE CURRENT_TIMESTAMP

推薦大多數(shù)場(chǎng)景用方案二,性能和一致性兼顧:

from sqlalchemy import func

stmt = (
    update(User)
    .where(User.status == 'pending')
    .values(status='processed', updated_at=func.now())
)
session.execute(stmt)
session.commit()

三個(gè)坑的本質(zhì)對(duì)比

坑一 pymysql坑二 mysql-connector坑三 SQLAlchemy
表面問(wèn)題異常沒(méi)回滾連接耗盡事件沒(méi)觸發(fā)
真實(shí)原因異常處理不完整連接池機(jī)制不同Core vs ORM 路徑差異
一句話解法except 里必寫(xiě) rollback()finally 里必關(guān)連接批量操作別用 Core 繞過(guò) ORM

這三個(gè)坑覆蓋了 異常流、資源管理、抽象層邊界 三個(gè)維度,踩過(guò)一次就不會(huì)再踩第二次。

以上就是Python操作MySQL數(shù)據(jù)庫(kù)時(shí)常見(jiàn)的三個(gè)陷阱及解決方法的詳細(xì)內(nèi)容,更多關(guān)于Python操作MySQL數(shù)據(jù)庫(kù)常見(jiàn)陷阱的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Python PIL圖片添加字體的例子

    Python PIL圖片添加字體的例子

    今天小編就為大家分享一篇Python PIL圖片添加字體的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-08-08
  • Python?web實(shí)戰(zhàn)教程之Django文件上傳和處理詳解

    Python?web實(shí)戰(zhàn)教程之Django文件上傳和處理詳解

    Django和Flask都是Python的Web框架,用于開(kāi)發(fā)Web應(yīng)用程序,這篇文章主要給大家介紹了關(guān)于Python?web實(shí)戰(zhàn)教程之Django文件上傳和處理的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • 使用tensorflow實(shí)現(xiàn)VGG網(wǎng)絡(luò),訓(xùn)練mnist數(shù)據(jù)集方式

    使用tensorflow實(shí)現(xiàn)VGG網(wǎng)絡(luò),訓(xùn)練mnist數(shù)據(jù)集方式

    這篇文章主要介紹了使用tensorflow實(shí)現(xiàn)VGG網(wǎng)絡(luò),訓(xùn)練mnist數(shù)據(jù)集方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-05-05
  • Python核心內(nèi)置函數(shù)len()、list()、locals()實(shí)用指南解析

    Python核心內(nèi)置函數(shù)len()、list()、locals()實(shí)用指南解析

    Python作為一門(mén)以簡(jiǎn)潔、易讀和強(qiáng)大功能著稱(chēng)的高級(jí)編程語(yǔ)言,其內(nèi)置函數(shù)是語(yǔ)言核心能力的重要體現(xiàn),也是初學(xué)者快速上手、中高級(jí)開(kāi)發(fā)者提升編碼效率的關(guān)鍵基石,這篇文章主要介紹了Python核心內(nèi)置函數(shù)len()、list()、locals()實(shí)用指南的相關(guān)資料,需要的朋友可以參考下
    2026-03-03
  • 解決csv.writer寫(xiě)入文件有多余的空行問(wèn)題

    解決csv.writer寫(xiě)入文件有多余的空行問(wèn)題

    今天小編就為大家分享一篇解決csv.writer寫(xiě)入文件有多余的空行問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • python制作填詞游戲步驟詳解

    python制作填詞游戲步驟詳解

    在本文里我們給大家整理了關(guān)于python制作填詞游戲的具體步驟以及實(shí)例代碼,需要的朋友們跟著學(xué)習(xí)下。
    2019-05-05
  • python實(shí)現(xiàn)dbscan算法

    python實(shí)現(xiàn)dbscan算法

    DBSCAN 算法是一種基于密度的空間聚類(lèi)算法,本文主要介紹了python實(shí)現(xiàn)dbscan算法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • Python中實(shí)現(xiàn)JWT認(rèn)證的完整指南(從生成到驗(yàn)證)

    Python中實(shí)現(xiàn)JWT認(rèn)證的完整指南(從生成到驗(yàn)證)

    JSON?Web?Tokens?(JWT)?是現(xiàn)代?Web?開(kāi)發(fā)中廣泛使用的身份驗(yàn)證機(jī)制,本文將用生動(dòng)的方式帶你全面了解?JWT?在?Python?中的實(shí)現(xiàn),包括生成、驗(yàn)證和各種相關(guān)方法,需要的朋友可以參考下
    2025-06-06
  • 總結(jié)Python函數(shù)參數(shù)的六種類(lèi)型

    總結(jié)Python函數(shù)參數(shù)的六種類(lèi)型

    這篇文章主要總結(jié)了Python函數(shù)參數(shù)的六種類(lèi)型,傳遞參數(shù)實(shí)現(xiàn)不同場(chǎng)景的靈活使用,下面總結(jié)的六種函數(shù)參數(shù)類(lèi)型,需要的小伙伴可以參考一下
    2022-03-03
  • python二分法查找實(shí)例代碼

    python二分法查找實(shí)例代碼

    二分算法是一種效率比較高的查找算法,其輸入的是一個(gè)有序的元素列表,如果查找元素包含在列表中,二分查找返回其位置,否則返回NONE,下面這篇文章主要給大家介紹了關(guān)于python二分法查找的相關(guān)資料,需要的朋友可以參考下
    2021-11-11

最新評(píng)論

兴国县| 彩票| 水城县| 吴川市| 宁晋县| 泰顺县| 黔南| 新安县| 龙陵县| 东安县| 烟台市| 洮南市| 齐齐哈尔市| 巴林右旗| 花莲市| 英德市| 津南区| 疏勒县| 井研县| 东辽县| 大兴区| 洪湖市| 广昌县| 昌黎县| 蒲城县| 平邑县| 垣曲县| 闽侯县| 湘潭市| 英山县| 开平市| 东宁县| 读书| 剑河县| 华阴市| 庆云县| 徐闻县| 天峻县| 特克斯县| 柏乡县| 陇西县|