MySQL 클라이언트를 MySQLDB로 자동 재연결하는 방법은?
PHP를 사용한 방법을 우연히 발견했습니다.
my_bool reconnect = 1;
mysql_options(&mysql, MYSQL_OPT_RECONNECT, &reconnect);
MySQLdb(python-mysql)에서는 운이 없습니다.
아무도 단서를 줄 수 있습니까?감사해요.
나는 이 문제를 해결하기 위해 감싼 기능을 만들었습니다.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
제안된 해결책이 예외를 못 잡아서 문제가 있었습니다.왜 그런지 잘 모르겠습니다.
나는 그 문제를 해결했습니다.ping(True)
내가 생각하기에 더 가깝다고 생각하는 진술:
import MySQLdb
con=MySQLdb.Connect()
con.ping(True)
cur=con.cursor()
여기서 확인: http://www.neotitans.com/resources/python/mysql-python-connection-error-2006.html
우분투 Linux를 사용하는 경우 python-mysql 패키지에 동일한 MYSQL_OPT_RECONNECT 옵션을 설정하는 기능이 추가된 패치가 있습니다(여기 참조).저는 안 먹어봤어요.
불행히도 패치는 나중에 자동 연결 및 변환(여기에 설명됨)과의 충돌로 인해 제거되었습니다.
해당 페이지의 의견은 다음과 같습니다. 1.2.2-7 2008-06-19에 용감무쌍하게 공개되었습니다.
python-mysqldb(1.2.2-7) 불안정; 긴급=낮음
[ Sandro Tosi ] * debian/control - 웹페이지에서 재포맷을 피하기 위해 설명에 항목 라인을 2칸으로 시작합니다 (닫힘: #480341)
[ Bernd Zeimetz ] * debian/patchs/02_reconnect.dpatch: - Droping patch: 문제를 설명하는 스톰의 코멘트:
# 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.
개릿과 비슷한 해결책이 필요했지만,cursor.execute()
, 내가 허락하고 싶은 대로MySQLdb
모든 탈출 임무를 대신 처리해 주시오래퍼 모듈은 결국 다음과 같은 모양이 되었습니다(아래 사용).
#!/usr/bin/env python
import MySQLdb
class DisconnectSafeCursor(object):
db = None
cursor = None
def __init__(self, db, cursor):
self.db = db
self.cursor = cursor
def close(self):
self.cursor.close()
def execute(self, *args, **kwargs):
try:
return self.cursor.execute(*args, **kwargs)
except MySQLdb.OperationalError:
self.db.reconnect()
self.cursor = self.db.cursor()
return self.cursor.execute(*args, **kwargs)
def fetchone(self):
return self.cursor.fetchone()
def fetchall(self):
return self.cursor.fetchall()
class DisconnectSafeConnection(object):
connect_args = None
connect_kwargs = None
conn = None
def __init__(self, *args, **kwargs):
self.connect_args = args
self.connect_kwargs = kwargs
self.reconnect()
def reconnect(self):
self.conn = MySQLdb.connect(*self.connect_args, **self.connect_kwargs)
def cursor(self, *args, **kwargs):
cur = self.conn.cursor(*args, **kwargs)
return DisconnectSafeCursor(self, cur)
def commit(self):
self.conn.commit()
def rollback(self):
self.conn.rollback()
disconnectSafeConnect = DisconnectSafeConnection
그것을 사용하는 것은 사소한 것이고, 단지 초기 연결만 다를 뿐입니다.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",))
커밋과 클로즈를 분리해서 연결할 수 있습니다...귀엽진 않지만 그래도 돼요.
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()
MySQL과 Python에도 비슷한 문제가 있었는데, 제게 도움이 된 솔루션은 MySQL을 5.0.27로 업그레이드하는 것이었습니다(페도라 Core 6에서는 시스템이 다른 버전에서 잘 작동할 수 있음).
Python 라이브러리를 패치하는 것을 포함하여 다른 많은 것을 시도했지만 데이터베이스를 업그레이드하는 것이 훨씬 쉬웠고 더 나은 결정이었다고 생각합니다.
Liviu Chircu 솔루션 ...에 추가하여 DisconnectSafeCursor에 다음 메서드를 추가합니다.
def __getattr__(self, name):
return getattr(self.cursor, name)
"마지막 행"과 같은 원래 커서 속성은 계속 작동합니다.
제 접근 방식은 리비우 치르쿠 솔루션을 기반으로 합니다.
너무 많은 재시도에 대한 통제를 추가했습니다.쿼리가 테이블 구조의 필드와 일치하지 않을 경우 리비우의 원래 답변이 "연결이 너무 많습니다" 작동 오류로 쉽게 이동할 수 있습니다.
MySQLdb.OperationalError: (1054, "Unknown column 'xxxxxxx' in 'field list'")
이 오류는 연결 오류가 아닙니다.제 버전에서는 클래스 변수가 필요 없다고 생각하여 제거했습니다.
import MySQLdb
class MySQLdbReconnectableCursor(object):
def __init__(self, db, cursor):
self.db = db
self.cursor = cursor
def __getattr__(self, name):
return getattr(self.cursor, name)
def __iter__(self, *args, **kwargs):
return self.cursor.__iter__(*args, **kwargs)
def __next__(self, *args, **kwargs):
return self.cursor.__next__(*args, **kwargs)
def close(self):
self.cursor.close()
def execute(self, *args, **kwargs):
try:
result = self.cursor.execute(*args, **kwargs)
self.db.refresh_retries()
return result
except MySQLdb.OperationalError:
self.db.reconnect(reraise=True)
self.cursor = self.db.cursor()
return self.cursor.execute(*args, **kwargs)
def fetchone(self):
return self.cursor.fetchone()
def fetchall(self):
return self.cursor.fetchall()
class MySQLdbReconnectable(object):
def __init__(self, *args, **kwargs):
self.conn = None
self.retries = kwargs.get("max_retries", 3)
self.connect_args = args
self.connect_kwargs = kwargs
self.refresh_retries()
self.reconnect()
def refresh_retries(self):
self.__retries = self.retries
def reconnect(self, reraise=False):
if self.__retries:
self.__retries -= 1
self.conn = MySQLdb.connect(
*self.connect_args, **self.connect_kwargs
)
else:
if reraise:
raise
else:
raise IOError("Can not retry anymore!")
def cursor(self, *args, **kwargs):
cur = self.conn.cursor(*args, **kwargs)
return MySQLdbReconnectableCursor(self, cur)
def commit(self):
self.conn.commit()
def rollback(self):
self.conn.rollback()
다른 사람들은 코드를 사용해서 직접 연결을 끊은 것을 해결하는 것에 베팅합니다.
이를 위한 한 가지 방법은 다음과 같습니다.
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
언급URL : https://stackoverflow.com/questions/207981/how-to-enable-mysql-client-auto-re-connect-with-mysqldb
'source' 카테고리의 다른 글
MySQL 로컬 변수 (0) | 2023.10.24 |
---|---|
설치 관리자가 파일을 인스턴스화할 수 없습니다...\KEY_XE.reg.파일이 존재하지 않는 것 같습니다. (0) | 2023.10.24 |
숨겨진 오버플로가 있는 스팬에서 점("...")을 표시하려면 어떻게 해야 합니까? (0) | 2023.10.24 |
oledb reader 또는 Excel library, Excel data reader 또는 NPOI 등(Interop 제외)을 통해 셀에 수식이 포함되어 있는지 확인하는 방법? (0) | 2023.10.24 |
마리아 DB에서 도시 선택을 더 잘 설명하는 방법은 무엇입니까? (0) | 2023.10.24 |