最近用 flask 寫了幾個介面部署在伺服器上,然後用 pytest 來做測試,但遇到了問題,搞了大半天才把問題解決。
問題大概是這樣的,我在本地環境用 pytest 寫**來對伺服器上 flask 的介面進行測試,在測試刪除介面的時候,第一步我在 pytest 中會通過sql插入資料到mysql資料庫,第二步再調刪除介面完成刪除使用者。最後執行 pytest **沒跑通過,會返回使用者不存在,但這個情況到資料庫裡檢視,發現該使用者實際是存在於mysql中。
首先,這個介面是沒啥大問題的,調註冊介面或手工插入資料,再手工請求訪問介面可以正常完成刪除,只是我在 pytest **中通過sql插入資料會出現這個問題。於是,感覺介面環境下通過 python 連線 pymysql ,查詢資料庫時,獲取到的似乎不是最新資料,所以調使用者刪除介面才會提示使用者不存在。接著,在網上查了下資料,發現是事務的隔離級別導致的這個問題。其次,懷疑自己 pytest **寫得有問題,但檢查後發現沒問題,並且加了查詢操作發現能查回這個新插入的資料。
最後,在各種排查後,在 flask 介面服務中,也加了查詢操作,但發現壓根沒查回這個新插入的資料。
mysql預設事務隔離級別是repeatable read
,當我在本地 pytest **中利用sql插入使用者資料並提交 commit 後,介面環境下的事務a不會讀取到我本地環境下的事務b更新的資訊,即便事務b已提交,而事務a每次查詢到的資料都是最開始建立事務查詢到結果的快照,事務a一直沒進行更新。更詳細的解釋說明,可參考文末列出的網上資料。
import pymysql
class mysqldb():
def __init__(self, host, port, user, passwd, db):
# 建立資料庫連線
self.conn = pymysql.connect(
host=host,
port=port,
user=user,
passwd=passwd,
db=db
)# 通過 cursor() 建立游標物件,並讓查詢結果以字典格式輸出
self.cur = self.conn.cursor(cursor=pymysql.cursors.dictcursor)
def __del__(self): # 物件資源被釋放時觸發,在物件即將被刪除時的最後操作
# 關閉游標
self.cur.close()
# 關閉資料庫連線
self.conn.close()
def select_db(self, sql):
"""查詢"""
# 檢查連線是否斷開,如果斷開就進行重連
self.conn.ping(reconnect=true)
# 使用 execute() 執行sql
self.cur.execute(sql)
# 使用 fetchall() 獲取查詢結果
data = self.cur.fetchall()
return data
def execute_db(self, sql):
"""更新/新增/刪除"""
try:
# 檢查連線是否斷開,如果斷開就進行重連
self.conn.ping(reconnect=true)
# 使用 execute() 執行sql
self.cur.execute(sql)
# 提交事務
self.conn.commit()
except exception as e:
print("操作出現錯誤:{}".format(e))
# 回滾所有更改
self.conn.rollback()
根據以上說明,要解決當前這個問題,我們可以通過以下方式來處理。
方法1:修改mysql的事務隔離級別在這裡,我們最好在方法2和方法3任選乙個方法來處理就行了,不建議去修改mysql的事務隔離級別。方法2:每次查詢操作後,都進行
commit()
提交事務。方法3:python建立pymysql連線時,設定
autocommit=true
,即讓其操作後自動提交事務。
def select_db(self, sql):
"""查詢"""
# 檢查連線是否斷開,如果斷開就進行重連
self.conn.ping(reconnect=true)
# 使用 execute() 執行sql
self.cur.execute(sql)
# 使用 fetchall() 獲取查詢結果
data = self.cur.fetchall()
# 提交事務
self.conn.commit()
return data
def __init__(self, host, port, user, passwd, db):
# 建立資料庫連線
self.conn = pymysql.connect(
host=host,
port=port,
user=user,
passwd=passwd,
db=db,
autocommit=true
)# 通過 cursor() 建立游標物件,並讓查詢結果以字典格式輸出
self.cur = self.conn.cursor(cursor=pymysql.cursors.dictcursor)
使用以上方法後,再次測試,發現問題已順利得到解決。
參考資料:
為什麼pymysql重連後才能查到被其他地方修改的資料 pymysql快取?
記一次pymysql查詢不到表中最新插入的資料的問題
解決PLSQL查不到帶中文條件的記錄
設定環境變數 重啟plsql nls lang american america.al32utf8 原因 客戶端與伺服器端編碼不一致 了解下nls lang的知識 nls lang 引數組成 nls lang 檢視oracle服務端編碼 select from sys.nls database pa...
Access模糊查詢查不到資料的解決方法
一般我們在程式裡寫模糊查詢時都是寫成如下這樣 select nbs程式設計客棧p from table where txttitle like 我們 不管連線的資料庫是access還是sql server 但是最近寫程式時總出現語句正確,但就是出不來結果的情況,比如 手動簡單設定伺服器安全,及引發的...
SQL查詢時間段查不到當日條目的解決方法
以前查詢都是直接取date this.datetimepicker1.value and date this.datetimepicker2.value的格式,相應列在sql裡存為datatime的格式,結果當天的記錄總是無法查到。原因在於datetimepicker.value的值的格式為xx x...