你可以使用与MySQLdb相同的连接执行多个原子提交

时间:2018-05-07 02:58:46

标签: mysql python-3.x transactions atomic

我希望能够使用Python3中的MySQLDb库使用相同的连接对象执行原子提交。我不认为有必要与数据库建立两个网络连接只是为了执行多个原子提交,但这似乎就是这种情况。是创建连接池的唯一选择吗?

例如,我希望能够做到这样的事情

conn = MySQLdb.connect(host="1.2.3.4", port=1234, user="root", passwd="x", db="test")

try:
    cur = conn.cursor()
    cur.execute("insert into my_table values (1, 2, 3)")
    cur.execute("insert into my_table values (4, 5, 6)")

    cur1 = conn.cursor()
    cur1.execute("insert into my_table values (12, 22, 32)")
    cur1.execute("insert into my_table values (42, 52, 62)")

    # Commit the last 2 inserts first
    # This won't work because cursor.commit() doesn't exist
    cur1.commit()

    # Now commit the first two inserts
    cur.commit() # Again, this won't work

except FailedTransaction as ex:
   # Rollback the actual transaction that failed.
   # Cursor aren't transactions, but there is no transaction
   # object so this is the best I can come up with. 
   ex.cursor.rollback()

conn.close()

1 个答案:

答案 0 :(得分:0)

不,MySQL在会话中没有不同的“级别”事务。只有一个当前事务,COMMIT或ROLLBACK会影响整个事务。

我认为我们可以同时打开MySQL的两个连接。这不需要连接池。 (连接池因其他原因而有用)。

shape

如果我们得到两个连接,那么我们应该能够在每个连接上独立运行事务 。 但这可能不适用于您的用例。假设InnoDB,如果在第一个连接上插入的行是群集密钥中的“最高”值,InnoDB会对索引的末尾进行独占索引锁定,从而阻止其他会话在群集密钥中执行具有更高值的插入。 (第二个会话将阻塞,直到获得所需的锁;并且在持有独占锁的会话释放它之前不会发生这种情况,使用ROLLBACK或COMMIT。)

锁定问题适用于所有索引,而不仅仅是群集密钥。

连接池无法解决该问题。

我所指的专属锁是“间隙锁”。如果我们对同一个表执行插入操作,我们将不得不解决锁定问题,以避免阻塞,等待锁定,当这些锁由我们的程序管理的会话持有时。

https://dev.mysql.com/doc/refman/5.7/en/glossary.html#glos_gap_lock

https://dev.mysql.com/doc/refman/5.7/en/innodb-locks-set.html