python mysql.connector 不承诺
python mysql.connector not committing
我在开发和测试环境中都有这个问题,第一个托管 MariaDB 数据库,另一个 MySQL 数据库:
我想在我的数据库中增加一个字段(避免竞争条件),所以我检索它,在具有可重复读取隔离级别的事务中增加和更新。
问题是该字段未在数据库中更新。
同时,如果我尝试使用 mysql 客户端直接执行 SQL 查询,它会按预期工作。
重要说明:我使用 self.conn.commit() 提交连接(如您在下面的代码中所见)
附加信息:
- 我不得不更改一些上传代码的变量名,所以如果您看到一些愚蠢的拼写错误(可能)不是问题所在。
- 我不得不显式地将 url 转换为 CHAR,因为它应该是一个像“12345.jpg”这样的字符串,它在带有 2 个参数的准备好的语句中出现了问题
- 经过多次尝试,代码可能有点乱,问题解决后会去掉一些多余的操作
相关函数如下:
import mysql.connector
class DbInteractor:
conn = None
cur = None
exception_message = 'Exception raised and handled by DbInteractor:\t'
def connect(self):
self.conn = mysql.connector.connect( ... )
def handle_closure(self, ex='', error=False):
if error:
print(self.exception_message, ex)
if self.cur:
self.cur.close()
cur = None
if self.conn:
self.conn.close()
conn = None
if error:
return -1
return 1
def set_cursor(self, prepared=True):
try:
self.connect()
except Exception as ex:
return self.handle_closure(ex, error=True)
try:
self.cur = self.conn.cursor(prepared=prepared)
except Exception as ex:
return self.handle_closure(ex, error=True)
return 1
def retrieve_number(self, url):
stmt = 'SELECT numbers FROM photos WHERE url = %s'
if not self.set_cursor():
if self.set_cursor() == -1:
return -1
try:
self.cur.execute(stmt, (url,))
number_list = self.cur.fetchall()
if len(number_list) != 1:
return self.handle_closure('failed numbers selection', error=True)
self.handle_closure()
result, = number_list[0]
return result
except Exception as ex:
self.handle_closure(ex, error=True)
return -1
def increment_number(self, url):
stmt = "UPDATE photos SET numbers = CAST(%s AS INT) WHERE url = CAST(%s AS CHAR);"
if self.set_cursor() == -1:
return -1
try:
self.conn.autocommit = False
self.conn.start_transaction(isolation_level='REPEATABLE READ')
numbers = self.retrieve_numbers(url)
print('prima: ', numbers)
if numbers == -1:
self.handle_closure('error incrementing numbers', error=True)
return -1
numbers += 1
tuple1 = (str(url), numbers)
self.set_cursor()
self.cur.execute(stmt, tuple1)
self.conn.commit()
print('dopo: ',numbers)
new_numbers = self.retrieve_numbers(url)
if new_numbers != numbers:
self.handle_closure('race condition incrementing numbers detected, can\'t rollback', error=True)
return -1
except Exception as ex:
self.handle_closure(ex, error=True)
return -1
self.handle_closure()
return 1
谢谢
反转元组,因为第一个%s是你cats的int,字符串是最后一个5S
tuple1 = ( numbers,str(url))
我在开发和测试环境中都有这个问题,第一个托管 MariaDB 数据库,另一个 MySQL 数据库:
我想在我的数据库中增加一个字段(避免竞争条件),所以我检索它,在具有可重复读取隔离级别的事务中增加和更新。 问题是该字段未在数据库中更新。 同时,如果我尝试使用 mysql 客户端直接执行 SQL 查询,它会按预期工作。
重要说明:我使用 self.conn.commit() 提交连接(如您在下面的代码中所见)
附加信息:
- 我不得不更改一些上传代码的变量名,所以如果您看到一些愚蠢的拼写错误(可能)不是问题所在。
- 我不得不显式地将 url 转换为 CHAR,因为它应该是一个像“12345.jpg”这样的字符串,它在带有 2 个参数的准备好的语句中出现了问题
- 经过多次尝试,代码可能有点乱,问题解决后会去掉一些多余的操作
相关函数如下:
import mysql.connector
class DbInteractor:
conn = None
cur = None
exception_message = 'Exception raised and handled by DbInteractor:\t'
def connect(self):
self.conn = mysql.connector.connect( ... )
def handle_closure(self, ex='', error=False):
if error:
print(self.exception_message, ex)
if self.cur:
self.cur.close()
cur = None
if self.conn:
self.conn.close()
conn = None
if error:
return -1
return 1
def set_cursor(self, prepared=True):
try:
self.connect()
except Exception as ex:
return self.handle_closure(ex, error=True)
try:
self.cur = self.conn.cursor(prepared=prepared)
except Exception as ex:
return self.handle_closure(ex, error=True)
return 1
def retrieve_number(self, url):
stmt = 'SELECT numbers FROM photos WHERE url = %s'
if not self.set_cursor():
if self.set_cursor() == -1:
return -1
try:
self.cur.execute(stmt, (url,))
number_list = self.cur.fetchall()
if len(number_list) != 1:
return self.handle_closure('failed numbers selection', error=True)
self.handle_closure()
result, = number_list[0]
return result
except Exception as ex:
self.handle_closure(ex, error=True)
return -1
def increment_number(self, url):
stmt = "UPDATE photos SET numbers = CAST(%s AS INT) WHERE url = CAST(%s AS CHAR);"
if self.set_cursor() == -1:
return -1
try:
self.conn.autocommit = False
self.conn.start_transaction(isolation_level='REPEATABLE READ')
numbers = self.retrieve_numbers(url)
print('prima: ', numbers)
if numbers == -1:
self.handle_closure('error incrementing numbers', error=True)
return -1
numbers += 1
tuple1 = (str(url), numbers)
self.set_cursor()
self.cur.execute(stmt, tuple1)
self.conn.commit()
print('dopo: ',numbers)
new_numbers = self.retrieve_numbers(url)
if new_numbers != numbers:
self.handle_closure('race condition incrementing numbers detected, can\'t rollback', error=True)
return -1
except Exception as ex:
self.handle_closure(ex, error=True)
return -1
self.handle_closure()
return 1
谢谢
反转元组,因为第一个%s是你cats的int,字符串是最后一个5S
tuple1 = ( numbers,str(url))