MySQL客戶端不需要commit代碼需要commit原因分析


一、客戶端與python在操作數據庫時的差別

在日常使用mysql客戶端操作mysql和使用python代碼操作mysql時,會發現他們不一致的地放:

在mysql客戶端中,不管是執行select還是執行delete等命令,都不需要commit;但在python代碼中我們經常要寫conn.commit()等代碼。

在mysql客戶端中,數據刪了就是刪了,即便用rollback命令進行回滾也沒什么用;但在python代碼中我們經常有如果執行sql語捕獲到異常,可使用conn.rollback()進行回滾的代碼。

 

二、從數據包分析兩者存在差別的根本原因

首先我們要明確兩個事情:一是客戶端和python代碼操作的服務器是同一個,所以存在差異的原因不可能是服務器造成的;二是從服務端角度而言他只能接收到發來的數據包,並不能知道這數據包是客戶端發來的還是python發來的。

所以也就是說,客戶端與python在操作數據庫時存在差別的原因,能且只能是客戶端和python給服務端發了不同的數據包造成的。

 

2.1 環境准備

當前表中有如下兩條記錄,我們分別用客戶端刪除id為0的記錄、python代碼刪除id為1的記錄,看兩者發送的數據包有何區別。

 

2.2 客戶端刪除數據時數據包交互過程

客戶端:workbench。

說明:也可以windows上安裝mysql然后直接使用mysql.exe,但注意不要ssh到服務器上再登錄數據庫,這樣抓到的包只能是ssh的數據包抓不到原始的mysql協議數據包。

 

 數據包交互過程如下。客戶端直接發送刪除命令服務端直接刪除成功:

 

2.3 python刪除數據交互過程

測試代碼如下:

import pymysql

def init_db(host="192.168.220.128",user="root",passwd="toor",db="test_db",charset="utf8"):
    try:
        conn = pymysql.connect(host, user, passwd, db, charset=charset)
    except Exception as e:
        print(e)
        exit(1)
    return conn

def delete_record(conn):
    cursor = conn.cursor()
    sql = "delete from test_table1 where id = 1"
    cursor.execute(sql)
    try:
        conn.commit()
    except:
        conn.rollback()

conn = init_db()
delete_record(conn)

數據包交互過程如下。首先是在連接數據庫時,框架自動給服務端發送了一條“SET AUTOCOMMIT = 0”的命令

 接下來python側再發送一條和客戶端類似的刪除命令:

 

 最后python中commit時再給服務端發送“COMMIT”命令:

 

 

2.4 總結

匯總以上兩個小節的數據。客戶端發送命令如下:

delete from test_table1 where id = 0

python代碼發送命令如下:

SET AUTOCOMMIT = 0
delete from test_table1 where id = 0
COMMIT

很容易可以得出結論:python代碼之所以相較客戶端需要commit,是因為python在連接數據庫時禁用了自動確認(SET AUTOCOMMIT = 0)。

另外我們不難得到一個推論:如果客戶端登錄后,用戶敲擊“SET AUTOCOMMIT = 0”,那么其后續在客戶端中對服務端的修改操作,將和python代碼一樣需要COMMIT、及如果刪完數據想反悔將可以ROLLBACK。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM