gpt4 book ai didi

python - 为什么没有人关心这个 MySQLdb 错误?这是一个错误吗?

转载 作者:IT王子 更新时间:2023-10-29 00:35:01 24 4
gpt4 key购买 nike

TL;DR:我已经为我发现的错误提供了补丁,但我收到的反馈为 0。我想知道这是否是一个错误。这不是咆哮。请阅读此内容,如果您可能受其影响,请检查修复。

我几周前发现并报告了这个 MySQLdb 错误(编辑:6 周前),发送了一个补丁,将其发布在几个 ORM 的论坛上,给 MySQLdb 作者发了邮件,给一些谈论处理死锁的人发了邮件,给 ORM 发了邮件作者和我仍在等待任何类型的反馈。

这个错误让我很伤心,我在反馈中能找到的唯一解释是没有人在 python 中使用“SELECT ... FOR UPDATE”和 mysql,或者这不是错误。

基本上,问题是当使用 MySQLdb 游标发出“SELECT ... FOR UPDATE”时,不会引发死锁和“锁定等待超时”异常。相反,该语句会默默地失败并返回一个空结果集,任何应用程序都会将其解释为好像没有匹配的行。

我已经测试了SVN版本,它仍然受到影响。在 Ubuntu Intrepid、Jaunty 和 Debian Lenny 的默认安装上进行了测试,它们也受到了影响。 easy_install (1.2.3c1) 安装的当前版本受到影响。

这也会影响 SQLAlchemy 和 SQLObject,并且可能任何使用 MySQLdb 游标的 ORM 也会受到影响。

此脚本可以重现将触发错误的死锁(只需更改 get_conn 中的用户/密码,它将创建必要的表):

import time
import threading
import traceback
import logging
import MySQLdb

def get_conn():
return MySQLdb.connect(host='localhost', db='TESTS',
user='tito', passwd='testing123')

class DeadlockTestThread(threading.Thread):
def __init__(self, order):
super(DeadlockTestThread, self).__init__()
self.first_select_done = threading.Event()
self.do_the_second_one = threading.Event()
self.order = order

def log(self, msg):
logging.info('%s: %s' % (self.getName(), msg))

def run(self):
db = get_conn()
c = db.cursor()
c.execute('BEGIN;')
query = 'SELECT * FROM locktest%i FOR UPDATE;'
try:
try:
c.execute(query % self.order[0])
self.first_select_done.set()

self.do_the_second_one.wait()
c.execute(query % self.order[1])
self.log('2nd SELECT OK, we got %i rows' % len(c.fetchall()))

c.execute('SHOW WARNINGS;')
self.log('SHOW WARNINGS: %s' % str(c.fetchall()))
except:
self.log('Failed! Rolling back')
c.execute('ROLLBACK;')
raise
else:
c.execute('COMMIT;')
finally:
c.close()
db.close()


def init():
db = get_conn()

# Create the tables.
c = db.cursor()
c.execute('DROP TABLE IF EXISTS locktest1;')
c.execute('DROP TABLE IF EXISTS locktest2;')
c.execute('''CREATE TABLE locktest1 (
a int(11), PRIMARY KEY(a)
) ENGINE=innodb;''')
c.execute('''CREATE TABLE locktest2 (
a int(11), PRIMARY KEY(a)
) ENGINE=innodb;''')
c.close()

# Insert some data.
c = db.cursor()
c.execute('BEGIN;')
c.execute('INSERT INTO locktest1 VALUES (123456);')
c.execute('INSERT INTO locktest2 VALUES (123456);')
c.execute('COMMIT;')
c.close()

db.close()

if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)

init()

t1 = DeadlockTestThread(order=[1, 2])
t2 = DeadlockTestThread(order=[2, 1])

t1.start()
t2.start()

# Wait till both threads did the 1st select.
t1.first_select_done.wait()
t2.first_select_done.wait()

# Let thread 1 continue, it will get wait for the lock
# at this point.
t1.do_the_second_one.set()

# Just make sure thread 1 is waiting for the lock.
time.sleep(0.1)

# This will trigger the deadlock and thread-2 will
# fail silently, getting 0 rows.
t2.do_the_second_one.set()

t1.join()
t2.join()

在未打补丁的 MySQLdb 上运行它的输出是这样的:

$ python bug_mysqldb_deadlock.py
INFO:root:Thread-2: 2nd SELECT OK, we got 0 rows
INFO:root:Thread-2: SHOW WARNINGS: (('Error', 1213L, 'Deadlock found when trying to get lock; try restarting transaction'),)
INFO:root:Thread-1: 2nd SELECT OK, we got 1 rows
INFO:root:Thread-1: SHOW WARNINGS: ()

您可以看到线程 2 从我们知道有 1 行的表中获得了 0 行,并且仅发出“SHOW WARNINGS”语句您就可以看到发生了什么。如果您检查“SHOW ENGINE INNODB STATUS”,您将在日志中看到这一行“*** WE ROLL BACK TRANSACTION (2)”,在 Thread-2 上失败的选择之后发生的所有事情都是半回滚事务。

应用补丁后(检查它的票,下面的 url),这是运行脚本的输出:

$ python bug_mysqldb_deadlock.py
INFO:root:Thread-2: Failed! Rolling back
Exception in thread Thread-2:
Traceback (most recent call last):
File "/usr/lib/python2.4/threading.py", line 442, in __bootstrap
self.run()
File "bug_mysqldb_deadlock.py", line 33, in run
c.execute(query % self.order[1])
File "/home/koba/Desarollo/InetPub/IBSRL/VirtualEnv-1.0-p2.4/lib/python2.4/site-packages/MySQL_python-1.2.2-py2.4-linux-x86_64.egg/MySQLdb/cursors.py", line 178, in execute
self.errorhandler(self, exc, value)
File "/home/koba/Desarollo/InetPub/IBSRL/VirtualEnv-1.0-p2.4/lib/python2.4/site-packages/MySQL_python-1.2.2-py2.4-linux-x86_64.egg/MySQLdb/connections.py", line 35, in defaulterrorhandler
raise errorclass, errorvalue
OperationalError: (1213, 'Deadlock found when trying to get lock; try restarting transaction')

INFO:root:Thread-1: 2nd SELECT OK, we got 1 rows
INFO:root:Thread-1: SHOW WARNINGS: ()

在这种情况下,Thread-2 会引发异常并正确回滚。

那么,你怎么看?这是一个错误吗?没人在乎,还是我疯了?

这是我在顺丰开的票:http://sourceforge.net/tracker/index.php?func=detail&aid=2776267&group_id=22307&atid=374932

最佳答案

Why doesn’t anyone care about this MySQLdb bug?

错误可能需要一段时间来确定优先级、研究、验证问题、找到修复、测试修复,确保修复修复不会破坏其他任何东西。我建议您部署一个变通办法,因为此修复可能需要一些时间才能到达。

关于python - 为什么没有人关心这个 MySQLdb 错误?这是一个错误吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/945482/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com