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函数则能触发数据规范化操作。
  • 大家有什么看法也欢迎指正哈!灰常感谢!

你可能感兴趣的:(python,数据库,errors)