programing

쿼리 중 MySQL 서버에 대한 연결이 끊어졌습니다.

copysource 2022. 10. 31. 23:40
반응형

쿼리 중 MySQL 서버에 대한 연결이 끊어졌습니다.

큰 테이블이 있는데 그 테이블에서 모든 행을 처리해야 합니다.연결 끊김 메시지가 항상 표시되지만 다시 연결하여 커서를 이전 위치로 복원할 수 없습니다.기본적으로 여기에 있는 코드는 다음과 같습니다.

#
import MySQLdb

class DB:
  conn = None

  def connect(self):
    self.conn = MySQLdb.connect('hostname', 'user', '*****', 'some_table', cursorclass=MySQLdb.cursors.SSCursor)

  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 bla FROM foo"
data = db.query(sql)

for row in data:
    do_something(row)
#

하지만 난 항상 이걸 듣죠.

#
Traceback (most recent call last):
  File "teste.py", line 124, in <module>
   run()
 File "teste.py", line 109, in run
   for row in data:
 File "/usr/lib64/python2.5/site-packages/MySQLdb/cursors.py", line 417, in next
   row = self.fetchone()
 File "/usr/lib64/python2.5/site-packages/MySQLdb/cursors.py", line 388, in fetchone
   r = self._fetch_row(1)
 File "/usr/lib64/python2.5/site-packages/MySQLdb/cursors.py", line 285, in _fetch_row
   return self._result.fetch_row(size, self._fetch_type)
   _mysql_exceptions.OperationalError: (2013, 'Lost connection to MySQL server during query')
    Exception _mysql_exceptions.OperationalError: (2013, 'Lost connection to MySQL server during query') in <bound method SSCursor.__del__ of <MySQLdb.cursors.SSCursor object at 0x7f7e3c8da410>> ignored
#

당신은 알기라도 하나요?

mysql 문서에는 다음 오류 전용 페이지가 있습니다.http://dev.mysql.com/doc/refman/5.0/en/gone-away.html

주목할 만한 것은

  • 서버에 올바르지 않거나 너무 큰 쿼리를 보내는 경우에도 이러한 오류가 발생할 수 있습니다.mysqld가 너무 크거나 잘못된 패킷을 수신하면 클라이언트에 문제가 있다고 가정하고 연결을 닫습니다.빅 쿼리가 필요한 경우(예를 들어 빅 BLOB 열을 사용하는 경우) 서버의 max_allowed_packet 변수를 설정하여 쿼리 제한을 늘릴 수 있습니다. 기본값은 1MB입니다.클라이언트 측에서 최대 패킷 크기를 늘려야 할 수도 있습니다.패킷 사이즈의 설정의 상세한 것에 대하여는, 섹션 B.5.2.10 「Packet too large」를 참조해 주세요.

  • --log-sysqld=2 옵션을 사용하여 mysqld를 시작하여 연결 끊김에 대한 자세한 정보를 얻을 수 있습니다.그러면 연결 해제된 오류 중 일부가 hostname.err 파일에 기록됩니다.

mysql 서버의 max_allowed_packet을 확대하려면 다음 3가지 방법이 있습니다.

  1. max_allowed_packet=64M/etc/mysql/my.cnf합니다.
  2. 합니다.mysql "sql " sql " sql " sql " .set global max_allowed_packet=67108864;
  3. Python은 mysql에 연결한 후 sql을 실행합니다.
connection.execute('set max_allowed_packet=67108864')

또한 하위 프로세스를 분기하는 응용 프로그램에서 모두 MySQL 서버에 동일한 연결을 사용하려는 경우에도 이 오류가 발생할 수 있습니다.이는 각 하위 프로세스에 대해 별도의 연결을 사용하여 방지할 수 있습니다.

포크가 맞을 수도 있어요.하지만 이런 경우에는 조심하지 마세요.

연결하기 전에 커서를 닫아야 합니다.이것으로 문제를 해결했습니다.

if cur and con:                        
    cur.close() 
    con.close() 

접속 타임아웃을 늘려야 합니다.어떤 이유로 할 수 없거나 하고 싶지 않은 경우 다음 번호로 전화를 걸 수 있습니다.

data = db.query(sql).store_result()

이렇게 하면 모든 결과를 즉시 가져올 수 있으며, 이러한 결과를 반복하는 도중에 연결이 시간 초과되지 않습니다.

그 이유를 설명하겠습니다.

오류 2013(HY000):쿼리 중 MySQL 서버에 대한 연결이 끊어졌습니다.

에러는 테이블의 일부가 파손되어 있는 것입니다.저도 할 수 없었어요.mysqldump상기와 같은 문제 등과 .이 에러는, 상기와 같은 메모리의 문제 등과는 관련이 없습니다.

다행인 것은 MySQL이 가장 먼저 실패한 행 번호를 돌려준 것입니다.뭐랄까...

mysqldump: 오류 2013: mytable을 행에 덤프할 때 쿼리 중 MySQL 서버에 대한 연결이 끊어졌습니다: 12723

해결책은 데이터를 새 테이블에 복사하는 것이었습니다.저 같은 경우에는 손상된 행을 건너뛰어야 했기 때문에 10개의 데이터가 손실되었습니다.먼저 기존 테이블 스키마를 사용하여 "tmp" 테이블을 만들었습니다. SHOW CREATE TABLE예:

SHOW CREATE TABLE mydatabase.mytable;

i로 새 테이블을 만들었습니다.mytabletmp라고 부르자.그런 다음 복사할 수 있는 행을 복사합니다.

insert into mysqltabletmp select * from mytable where id < 12723;
insert into mysqltabletmp select * from mytable where id > 12733;

오래된 테이블을 드롭한 후 tmp-table 이름을 오래된 테이블 이름으로 변경합니다.

문제에 관한 피터로부터의 좋은 정보도 있습니다.

이 일어난 은 내가 mariadb를 이다. 왜냐하면 내가 한 말 때문에varchar(255)a열로 하다unique key유니크한 것 치고는 너무 무거운 것 같아요. 츠키노

멀티프로세싱과 장고DB는 서로 잘 어울리지 않습니다.

새로운 프로세스에서 가장 먼저 Django DB 연결을 종료하게 되었습니다.

따라서 부모에 의해 사용되는 접속에 대한 참조가 없어집니다.

from multiprocessing import Pool

multi_core_arg = [[1,2,3], [4,5,6], [7,8,9]]
n_cpu = 4
pool = Pool(n_cpu)
pool.map(_etl_, multi_core_arg)
pool.close()
pool.join()

def _etl_(x):
    from django.db import connection 
    connection.close() 
    print(x)

또는

Process.start() calls calls calls calls calls which which which which which which which which which which which로 시작하는 합니다.

또 다른 일부에서는

from multiprocessing.dummy import Pool as ThreadPool

(2013년, 연결 끊김) 문제는 해결되었지만 스레드에서는 I/O 시 GIL을 사용하여 I/O가 완료되면 해제됩니다.

상대적으로 프로세스는 서로 통신하는 작업자 그룹을 생성하며, 작업자 그룹은 더 느릴 수 있습니다.

시간을 재보는 것을 추천합니다.skikit-learn 프로젝트가 뒷받침된 joblib을 사용하는 것도 한 가지 팁입니다.퍼포먼스 결과에 따라서는 네이티브 풀()을 실행합니다.그러나 실제 실행 시간 비용을 확인할 책임은 코딩자에게 있습니다.

'max_allowed_packet' 설정을 64M으로 설정하고 MySql 서버를 재시작합니다.이 방법으로 문제가 해결되지 않으면 다른 곳에 문제가 있을 수 있습니다.

동시 쿼리를 실행하는 멀티 스레드 PHP CLI 응용 프로그램을 사용했는데 최근에 이 문제를 발견했습니다.이제 MySql 서버가 동일한 IP의 모든 연결을 '단일' 연결로 간주하므로 단일 쿼리가 완료될 때마다 모든 연결을 끊는다는 것을 알 수 있습니다.

MySql이 같은 IP에서 100개의 접속을 허용하고 각각의 접속을 개별 접속으로 간주할 수 있는 방법이 있는지 궁금합니다.

저도 비슷한 문제를 겪었어요.제 경우, 다음과 같이 커서를 가져옴으로써 해결되었습니다.

cursor = self.conn.cursor(buffered=True)

@하지만 @imxylz를 . ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★mycursor.execute('set GLOBAL max_allowed_packet=67108864')GLOBAL 파라미터를 사용하지 않고 읽기 전용 오류가 발생했기 때문입니다.

mysql.connector.__version__ 

8.0.16

문제는 KILL 명령어를 사용하여 누군가 또는 무언가가 연결을 끊은 경우에도 발생할 수 있습니다.

이 문제는 디스크의 크기가 사용 가능한 디스크 공간보다 큰 테이블을 업데이트하려고 할 때 발생했습니다.그 해결책은 단순히 사용 가능한 디스크 공간을 늘리는 것이었습니다.

제 경우 테이블을 잘못된 순서로 배치한 SQL 덤프를 소싱할 때 이 문제가 발생했습니다.문제의 CREATE에는 제약 조건이 포함되어 있습니다.아직 생성되지 않은 테이블을 참조한 참조입니다.

문제의 테이블을 찾아 CREATE 스테이트먼트를 문제의 스테이트먼트 이상으로 이동시켰더니 에러가 사라졌습니다.

이 장애 덤프와 관련하여 발생한 다른 오류는 ERROR 1005/errno: 150 -- "Cannot create table" 이었습니다.이것은 테이블이 정상적으로 작성되지 않은 문제입니다.

이 일은 내 인생에서 일어났을 때CONSTRAINTCONSTRAINTdisclossible을 클릭합니다.

의 ★★★★★★★★★★★★★★★의 변경CONSTRAINT이치노

저도 같은 문제에 부딪혔어요. 밖에도 몇 가 있기 때문에, 저는 '하다'를 추가하려고 .cnx.close()다른 기능에 대응합니다.대신 이 모든 관련 없는 닫힘을 제거하고 클래스를 다음과 같이 설정했습니다.

class DBase:

config = {
      'user': 'root',
      'password': '',
      'host': '127.0.0.1',
      'database': 'bio',
      'raise_on_warnings': True,
      'use_pure': False,
      }

def __init__(self):
    import mysql.connector
    self.cnx = mysql.connector.connect(**self.config)
    self.cur = self.cnx.cursor(buffered=True)
    print(self.cnx)
def __enter__(self):
    return DBase()

def __exit__(self, exc_type, exc_val, exc_tb):
    self.cnx.commit()
    if self.cnx:
        self.cnx.close()

이 클래스 내에서 호출되는 함수는 connect, commit 및 close입니다.

수백만 개의 레코드로 대량 삽입을 시도했을 때 "파이프 파손"으로 인해 오류가 발생했습니다.이 문제를 해결하려면 데이터를 더 작은 배치 크기로 청크한 다음 필요한 삽입마다 mysql 커서가 있는 executemany 명령을 실행해야 합니다.이것으로 문제가 해결되어 퍼포먼스에 눈에 띄는 영향은 없는 것 같습니다.

예:

def chunks(data):
    for i in range(0, len(data), CHUNK_SIZE):
        yield data[i:i + CHUNK_SIZE]


def bulk_import(update_list):
    new_list = list(chunks(update_list))
    for batch in new_list:
         cursor.execute(#SQL STATEMENT HERE)

유사한 문제에 대한 답변이 이어지는 것을 볼 수 있습니다.

https://stackoverflow.com/a/69610550/16647254

이 문제를 해결하기 위해 잠금을 사용하다

lock.acquire()
mysqlhelper.getconn()
result_db_num = mysqlhelper.update(sql, [businessid, md5_id])
mysqlhelper.end()
mysqlhelper.dispose()
lock.release()

나는 같은 문제를 안고 여러 가지 해결책을 시도하며 몇 시간 동안 씨름했다.결국 나에게 효과가 있었던 것은 이것이었다.이 코드는 처음에 10개의 연결 풀을 열고 다음으로 mysql.connector가 get_connection()을 사용하여 풀에서 연결을 제공합니다.

class DB:
    connection = None

    def __init__(self):
        self.conn()

    def conn(self):
        try:
            if not self.connection:
                self.connection = mysql.connector.pooling.MySQLConnectionPool(user='web', password='mypasswd',
                                                                              host='prod', database='myelection',
                                                                              autocommit=True, pool_size=10,
                                                                              buffered=True)
            return self.connection.get_connection()

        except mysql.connector.errors.InterfaceError as err:
            print("can't connect to mysql ", err)

        except mysql.connector.DatabaseError as err:
            print("database error: ", err)

        except Exception as err:
            print("unknown db exception: ", err)

        print("exiting from conn() with error.")
        exit()

    # Make sure your class methods open, then automatically 
    # close the connections and the cursors.
    def new_polling_place(self, pp_name):
        #  cur = self.conn().cursor(dictionary=True)
        with self.conn() as con:
            with con.cursor() as cur:
                cur.execute("INSERT INTO pollingplace (pp_name) VALUES (%s)", [pp_name])
                return cur.lastrowid

이 같은 상황은 제가 작업하는 동안에도 일어났습니다.mariadb ,sqlalchemy그리고.pandas그리고 마치@iamapotatoe위에서는 데이터 프레임을 청크로 분할하여 sql 데이터베이스에 조금씩 포팅하는 기능도 만들었습니다.이것은, 특히, RPV를 변경했을 경우에 이용할 수 있습니다.max_allowed_packetmysql config 옵션에서 사용할 수 없습니다.

def load_large_df(table_name,df_to_load,batch_size,engine):
    df_to_load = df_to_load.dropna(how='all')
    with engine.connect() as conn:
        conn.execute(f"DROP TABLE IF EXISTS {table_name}")
        rows = df_to_load.shape[0]
        batch = int(rows/batch_size)
        

        strt = 0
        while strt < rows:
            df = df_to_load[strt:].head(batch)
            df.to_sql(table_name,con=conn,if_exists='append')
            strt += batch

phpadmin의 제어판에 접속하여 config/ini 파일을 클릭하여 .ini 파일을 편집합니다.접속에 사용하고 있는 포토가 아닌 경우는, 포토 3306을 사용하고 있는 포토로 변경합니다.로그인 화면에서 서버의 localhost를 입력합니다.기본값이 아니거나 sql configuration leave에서 my.ini 파일명을 변경하지 않은 경우 port를 입력합니다.username:root 또는 작성한 파일명, 패스워드:1234 또는 할당한 파일명을 입력합니다.localy 에 접속하고 있는 경우는, url 옵션을 선택하지 말아 주세요.편집할 데이터베이스의 이름을 입력합니다.참고: 연결되면 서버 또는 연결 중인 서버에 있는 데이터베이스 목록이 표시됩니다.

언급URL : https://stackoverflow.com/questions/1884859/lost-connection-to-mysql-server-during-query

반응형