pymysql 事務中的外碼約束問題

問題
  1. 首先自己寫了個事務內執行多個sql的包裝函數,使得這些sql的操作具有原子性,中間任意一條操作出現錯誤都會拋出異常並回退。
   # 更新數據,可以執行數據的增、刪、改
   ...
    def update_data(self, sqls: list):
        connect = self.__get_connect()
        cursor = connect.cursor()
        try:
            for sql in sqls:
                cursor.execute(sql)
            connect.commit()
        except Exception:
        	# 出現異常則回滾,並拋出異常
            connect.rollback()
            raise
        finally:
            cursor.close()
            connect.close()
  1. 然後在執行下邊的sqls時出現了異常
"""scheme
CREATE table1 (
	id: INTEGER PRIMARY KEY
);
CREATE table2 (
	id: INTEGER PRIMARY KEY,
	foreign_id: INTEGER ,
	FOREIGN KEY(foreign_id) REFERENCES table1(id)
);
"""
sqls = [
	'INSERT INTO table1(id) VALUES(1);',
	'INSERT INTO table2(id, foreign_id) VALUES(1, 1);'
]
update_data(sqls)

# >>> 異常(1452, 'Cannot add or update a child row: a foreign key constraint fails ...')
  1. 違反外碼約束?也就是說,在事務內,execute(sql)後緩存區的新插入數據若未commit是不能被下一條sql獲取的麼…
解決方法

經過一番瞎試,找到了以下的應對方法,在execute(sql)fetch一下

   # 更新數據,可以執行數據的增、刪、改
   ...
    def update_data(self, sqls: list):
        connect = self.__get_connect()
        cursor = connect.cursor()
        try:
            for sql in sqls:
                cursor.execute(sql)
                cursor.fetchone()	# 解決方法
            connect.commit()
        except Exception:
        	# 出現異常則回滾,並拋出異常
            connect.rollback()
            raise
        finally:
            cursor.close()
            connect.close()
  • 看了官網文檔以及網上的一些fetch方法的介紹,由於我python跟mysql也不是很熟悉,還是沒找到fetch能解決這個問題的原因
  • 我自己考慮的是,pymysql事務的緩存機制中,緩存區也有兩個部分,一個部分是準備就緒的數據,這些數據經過了處理,比較符合mysql數據庫規範,即將commit到數據庫中,此時能被事務中的其他操作獲取另一部分的數據還未準備就緒,仍未進行規範化處理,不能被事務中的其他操作獲取。分區的目的也顯而易見,準備就緒的數據在進行規範化時是比較耗時的。execute後的數據默認分配到就緒區,而fetch函數則能觸發數據規範化操作。
  • 大家有什麼看法也歡迎指正哈!灰常感謝!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章