Python 如何启用MySQL客户端与MySQLdb的自动重新连接?

Python 如何启用MySQL客户端与MySQLdb的自动重新连接?,python,mysql,Python,Mysql,我偶然发现了PHP的技巧: my_bool reconnect = 1; mysql_options(&mysql, MYSQL_OPT_RECONNECT, &reconnect); 但是MySQLdb(pythonmysql)没有运气 谁能给我一个线索吗?谢谢。如果您使用的是ubuntu Linux,则python mysql包中添加了一个补丁,该补丁增加了设置相同mysql_OPT_RECONNECT选项的功能(请参阅)。不过我还没有试过 不幸的是,由于与自动连接和事务处

我偶然发现了PHP的技巧:

my_bool reconnect = 1;
mysql_options(&mysql, MYSQL_OPT_RECONNECT, &reconnect);
但是MySQLdb(pythonmysql)没有运气


谁能给我一个线索吗?谢谢。

如果您使用的是ubuntu Linux,则python mysql包中添加了一个补丁,该补丁增加了设置相同mysql_OPT_RECONNECT选项的功能(请参阅)。不过我还没有试过

不幸的是,由于与自动连接和事务处理(如上所述)冲突,该修补程序后来被删除

该页面的评论说: 1.2.2-7发布于2008年6月19日的《无畏》发行版

python mysqldb(1.2.2-7)不稳定;紧急程度=低

[托西先生] *debian/control -描述中的列表项行以2个空格开头,以避免重新格式化 在网页上(关闭:#480341)

[Bernd Zeimetz] *debian/patches/02_reconnect.dpatch: -放置修补程序: 解释问题的风暴评论:

    # Here is another sad story about bad transactional behavior. MySQL
    # offers a feature to automatically reconnect dropped connections.
    # What sounds like a dream, is actually a nightmare for anyone who
    # is dealing with transactions. When a reconnection happens, the
    # currently running transaction is transparently rolled back, and
    # everything that was being done is lost, without notice. Not only
    # that, but the connection may be put back in AUTOCOMMIT mode, even
    # when that's not the default MySQLdb behavior. The MySQL developers
    # quickly understood that this is a terrible idea, and removed the
    # behavior in MySQL 5.0.3. Unfortunately, Debian and Ubuntu still
    # have a patch right now which *reenables* that behavior by default
    # even past version 5.0.3.

你可以用代码来解决掉的连接

一种方法是:

import MySQLdb

class DB:
    conn = None

    def connect(self):
        self.conn = MySQLdb.connect()

    def cursor(self):
        try:
            return self.conn.cursor()
        except (AttributeError, MySQLdb.OperationalError):
            self.connect()
            return self.conn.cursor()

db = DB()
cur = db.cursor()
# wait a long time for the Mysql connection to timeout
cur = db.cursor()
# still works

我在MySQL和Python上也遇到了类似的问题,对我有效的解决方案是将MySQL升级到5.0.27(在FedoraCore6上;您的系统可以在不同的版本下正常工作)


我尝试了很多其他的事情,包括修补Python库,但是升级数据库要容易得多,而且(我认为)是一个更好的决定。

我通过创建一个包装
cursor.execute()
方法的函数来解决这个问题,因为这就是引发
MySQLdb.OperationalError
异常的原因。上面的另一个示例意味着抛出此异常的是
conn.cursor()
方法

import MySQLdb

class DB:
  conn = None

  def connect(self):
    self.conn = MySQLdb.connect()

  def query(self, sql):
    try:
      cursor = self.conn.cursor()
      cursor.execute(sql)
    except (AttributeError, MySQLdb.OperationalError):
      self.connect()
      cursor = self.conn.cursor()
      cursor.execute(sql)
    return cursor

db = DB()
sql = "SELECT * FROM foo"
cur = db.query(sql)
# wait a long time for the Mysql connection to timeout
cur = db.query(sql)
# still works

您可以将连接的提交和关闭分开…这并不可爱,但它确实做到了

class SqlManager(object):
 """
 Class that handle the database operation
 """
 def __init__(self,server, database, username, pswd):

      self.server = server
      self.dataBase = database
      self.userID = username
      self.password = pswd

def Close_Transation(self):
      """
      Commit the SQL Query
      """
      try:
        self.conn.commit()
      except Sql.Error, e:
        print "-- reading SQL Error %d: %s" % (e.args[0], e.args[1])

 def Close_db(self):
    try:
        self.conn.close()
    except Sql.Error, e:
        print "-- reading SQL Error %d: %s" % (e.args[0], e.args[1])

 def __del__(self):
    print "close connection with database.."
    self.conn.close() 

我对提议的解决方案有问题,因为它没有捕获异常。我不知道为什么

我已经用
ping(True)
语句解决了这个问题,我认为它更简洁:

import MySQLdb
con=MySQLdb.Connect()
con.ping(True)
cur=con.cursor()

从这里了解到:

我需要一个类似于Garret的解决方案,但用于
cursor.execute()
,因为我想让
MySQLdb
为我处理所有转义任务。包装器模块的最终外观如下(用法如下所示):

使用它很简单,只是初始连接不同。根据MySQLdb的需要,使用包装器方法扩展类

import mydb

db = mydb.disconnectSafeConnect()
# ... use as a regular MySQLdb.connections.Connection object

cursor = db.cursor()

# no more "2006: MySQL server has gone away" exceptions now
cursor.execute("SELECT * FROM foo WHERE bar=%s", ("baz",))

除了Liviu Chircu溶液。。。添加以下方法以断开SafeCursor的连接:

def __getattr__(self, name):
    return getattr(self.cursor, name)

并且原始游标属性(如“lastrowid”)将继续工作。

我猜无论客户端做什么,连接丢失都可能表示事务丢失(服务器已断电)或连接丢失。所以我同意,简单的重新连接可能会隐藏数据丢失,而不是mysql客户机用户的预期。实际上,这个方法不起作用。创建游标不会与DB建立连接,因此不会引发OperationError异常。@garret heaton-为什么要在AttributeError上重新连接?当连接过时时也会抛出这个错误吗?有一段时间我试图找出我的包装中偶尔出现的mysql错误。起初我以为
conn.open
会起作用的,不。。。但这是有效的。如果重新连接,您应该知道您丢失了所有
@变量
设置
。另外,完成了一半的事务将被回滚。这可能会导致一些混乱。@aaa90210:AttributeError用于捕获self.conn仍然为“None”(数据库尚未连接)的情况,而查询方法尝试“cursor=self.conn.cursor()”。我只想指出,这还将捕获其他错误:
OperationalError:(1054,“字段列表”中的未知列“country”).
也许2009年的情况有所不同,但我只是说。我正在将我的脚本生成16-20个子进程,而我的mysql出现了问题。con.ping(True)修复了我的问题。谢谢。在运行查询之前ping被认为是一种浪费资源且不可靠的反模式:这应该是第一个答案。比其他的更强大。真的很好!谢谢
def __getattr__(self, name):
    return getattr(self.cursor, name)