MySQL、RDS、锁定超时
MySQL, RDS, Lock timeout
我正在创建一个应用程序,它使用 RDS 的 MySQL 实例,由节点和 python 程序访问。节点端很好,直到几天前 python 端也很好。现在 python 程序在简单查询时失败了:
我 运行 通过上下文管理器进行查询,如下所示:
with safeExecute(dbConnection.cursor()) as cursor:
log('about to run SQL')
sql = """UPDATE ts
SET ts.fails = ts.fails + 1,
ts.attempts = ts.attempts + 1
WHERE ts.id = 206 """
cursor.execute(sql)
log('sql executed')
@contextmanager
def safeExecute(cursor):
try:
yield cursor
log('attempting to commit')
dbConnection.commit()
log('committed')
except MySQLdb.OperationalError as e:
dbConnection.rollback()
log("--CRITICAL--")
traceback.print_exc()
sys.exit(1)
except Exception as e:
dbConnection.rollback()
log("Caught DB exception: ")
traceback.print_exc()
sys.stdout.flush()
finally:
cursor.close()
控制台日志将如下所示:
about to run sql
sql executed
attempting to commit
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
OR
OperationalError: (2006, 'MySQL server has gone away')
奇怪的是,这个错误是间歇性的,不会总是到达同一点。有时 attempting to commit
会出现,而其他时候它永远不会超过 cursor.execute()
。
我还有 2 个类似的查询,只是更新了各种计数器。它有时会毫无问题地执行所有 3 个,有时会卡在其中一个上。这个应用程序不应该有任何并发问题,它处理大约 30 秒,然后按顺序运行上面的这些查询(因此不应该有任何竞争条件)。
但是,查看打开的表它似乎没有被锁定(当我执行以下查询时查询是 运行)
mysql> show open tables where in_use>0;
+------------+------------+--------+-------------+
| Database | Table | In_use | Name_locked |
+------------+------------+--------+-------------+
| tearsheets | tearsheets | 1 | 0 |
+------------+------------+--------+-------------+
Show processlist
也没有透露任何信息。事实上,它表明连接正在休眠:
ID | USER | HOST | DB | COMMAND | TIME | STATE | INFO |
1230255 | <username> | <ip-address> | <ts table> | Sleep | 42 | | NULL
state
是空白的,那里没有文字...
我该如何进一步调试呢?我不确定还要看什么。
我通过简单地在每次事务后关闭连接,然后为下一次数据库交互重新打开一个新事务来解决这个问题。不确定我的问题的最初原因是什么,但现在似乎有效了。
我正在创建一个应用程序,它使用 RDS 的 MySQL 实例,由节点和 python 程序访问。节点端很好,直到几天前 python 端也很好。现在 python 程序在简单查询时失败了:
我 运行 通过上下文管理器进行查询,如下所示:
with safeExecute(dbConnection.cursor()) as cursor:
log('about to run SQL')
sql = """UPDATE ts
SET ts.fails = ts.fails + 1,
ts.attempts = ts.attempts + 1
WHERE ts.id = 206 """
cursor.execute(sql)
log('sql executed')
@contextmanager
def safeExecute(cursor):
try:
yield cursor
log('attempting to commit')
dbConnection.commit()
log('committed')
except MySQLdb.OperationalError as e:
dbConnection.rollback()
log("--CRITICAL--")
traceback.print_exc()
sys.exit(1)
except Exception as e:
dbConnection.rollback()
log("Caught DB exception: ")
traceback.print_exc()
sys.stdout.flush()
finally:
cursor.close()
控制台日志将如下所示:
about to run sql
sql executed
attempting to commit
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
OR
OperationalError: (2006, 'MySQL server has gone away')
奇怪的是,这个错误是间歇性的,不会总是到达同一点。有时 attempting to commit
会出现,而其他时候它永远不会超过 cursor.execute()
。
我还有 2 个类似的查询,只是更新了各种计数器。它有时会毫无问题地执行所有 3 个,有时会卡在其中一个上。这个应用程序不应该有任何并发问题,它处理大约 30 秒,然后按顺序运行上面的这些查询(因此不应该有任何竞争条件)。
但是,查看打开的表它似乎没有被锁定(当我执行以下查询时查询是 运行)
mysql> show open tables where in_use>0;
+------------+------------+--------+-------------+
| Database | Table | In_use | Name_locked |
+------------+------------+--------+-------------+
| tearsheets | tearsheets | 1 | 0 |
+------------+------------+--------+-------------+
Show processlist
也没有透露任何信息。事实上,它表明连接正在休眠:
ID | USER | HOST | DB | COMMAND | TIME | STATE | INFO |
1230255 | <username> | <ip-address> | <ts table> | Sleep | 42 | | NULL
state
是空白的,那里没有文字...
我该如何进一步调试呢?我不确定还要看什么。
我通过简单地在每次事务后关闭连接,然后为下一次数据库交互重新打开一个新事务来解决这个问题。不确定我的问题的最初原因是什么,但现在似乎有效了。