LINUX.ORG.RU

Python+MySQLdb: «MySQL server has gone away»


0

1

Пробую делать кучу INSERT/UPDATE'ов в несколько потоков на Python, используя connection pooling.
Вот что выдается во время работы:

SQL Error: (2014, "Commands out of sync; you can't run this command now")
SQL Error: (2006, 'MySQL server has gone away')
Почему? О каких ошибках это может говорить?
В Гугле смотрел - ничего из перечисленного там не подходит: http://www.mysql.ru/docs/man/Gone_away.html
P.S. Код слишком большой, его здесь не привожу, SQL-запросы самые обычные - простой UPDATE и INSERT с десятком полей.

★★★★★

оно хоть с транзакциями?

пастебин придуман для большого кода, если конечно лицензия на него не анально-копирастическая

anonymous ()
Ответ на: комментарий от anonymous

> если конечно лицензия на него не анально-копирастическая

Стыдно код показывать, там база данных - очень уродливая + ТЗ на программу практически отсутствовало.

Интересуют предположения о том - почему такие ошибки могут быть.
Схема программы примерно такая:
http://php.kirovnet.ru/connection-pooling.html

pacify ★★★★★ ()
Ответ на: комментарий от anonymous

оно хоть с транзакциями?

Насчет транзакций я не понял - я в этом практически ничего не понимаю.
Основной участок кода:

def sql_execute_ex (j,query1,params1,query2,params2,query3,params3):
  global n_t_sql
  global f_conn
  global a_conn
  try:
    print j,
    cur = a_conn[j].cursor()
##    cur.execute (query1,params1)
##    row = cur.fetchone()
##    if row <> None:
    # INSERT
    try:
      sys.stdout.write("+")
      if query3 <> "":
        cur.execute (query3,params3)
    # UPDATE
    except:
      sys.stdout.write(":")
      if query2 <> "":
        cur.execute (query2,params2)
    sys.stdout.write("*")
    f_conn[j] = False
    n_t_sql = n_t_sql - 1
    sys.stdout.write(">")
  except Exception,e:
    print "SQL Error: %s [%s]" % (str(e),query1+query2+query3)
    f_conn[j] = False
    n_t_sql = n_t_sql - 1
    sys.stdout.write(">")

def sql_ex (query1,params1,query2,params2,query3,params3):
  global n_t_sql
  global f_conn
  while True:
    j = -1
    for k in xrange(NTMAX_SQL):
      if (f_conn[k] == False):
        j = k
        break;
    if j <> -1: break;
    time.sleep(0.1)
  f_conn[j] = True
  n_t_sql = n_t_sql + 1
  thread.start_new (sql_execute_ex, (j,query1,params1,query2,params2,query3,params3,))
Какой код еще показать?

pacify ★★★★★ ()
Ответ на: комментарий от pacify

надо попробовать проверять не закрыто ли соединение с сервером перед инсертами/апдейтами. может в этом вся соль

anonymous ()
Ответ на: комментарий от pacify

Меня смущает конструкция

    # INSERT
    try:
      sys.stdout.write("+")
      if query3 <> "":
        cur.execute (query3,params3)
    # UPDATE
    except:
      sys.stdout.write(":")
      if query2 <> "":
        cur.execute (query2,params2)

такого except лучше избежать, либо используя SELECT и потом INSERT или UPDATE без вызова exception, либо может подойдет конструкция INSERT ... ON DUBLICATE KEY UPDATE

Вполне возможно что после exception нужно сделать ROLLBACK транзацкии если она у тебя автоматом открылась.

zhiltsov ()

О каких ошибках это может говорить?

отвалился сервер. Посмотри в его лог ошибок, скорее всего ему кирдык.

true_admin ★★★★★ ()
Ответ на: комментарий от true_admin

> отвалился сервер

Он каждый раз отваливается при запуске этой программы.
Сейчас тестируем с принудительным begin(), commit(), rollback()

pacify ★★★★★ ()
Ответ на: комментарий от pacify

ну тогда надо разобраться с этим. Может база повреждена, может просто версия старая и глючная. Может железо глючное...

true_admin ★★★★★ ()
Ответ на: комментарий от true_admin

Вернее, она наверняка повреждена при падении mysqld если у вас myisam. Хотя, если используете begin/commit то значит что у вас innodb. Но он тоже может хитро поломаться....

true_admin ★★★★★ ()
Ответ на: комментарий от mashina

> не myisam ли таблицы используются?

Да, именно - MyISAM (я в этом не разбираюсь, это у заказчика на сервере стоит, он мою программу тестирует).
База там очень большая.

pacify ★★★★★ ()
Ответ на: комментарий от pacify

myisam не может работать с конкурирующими w (запись) потоками ибо использует при обновлении эксклюзивные блокировки на всю таблицу. Т.е. долбить его в несколько потоков с INSERT/UPDATE из приложения смысла не имеет.

mashina ★★★★★ ()
Ответ на: комментарий от mashina

> myisam не может работать с конкурирующими w (запись) потоками ибо

использует при обновлении эксклюзивные блокировки на всю таблицу.


Хм. То есть, распараллелить INSERT/UPDATE для MyISAM невозможно?
Испольуется небольшой набор таблиц, программа работает в 15-20 потоков.

P.S. Иногда после этих ошибок скрипт вываливался в Segmentation fault (Python2.5, FreeBSD).

pacify ★★★★★ ()
Ответ на: комментарий от pacify

Если всё это идет к одной таблице, то да, база просто уйдёт в DoS из-за блокировок. Если инсерты/апдейты идут к разным таблицам, то можно в несколько потоков, но нужно как-то делать так, чтобы они одновременно не работали с одной и той же таблицей.

Почему там получается сегфолт хз, по идее не должно такого быть.

mashina ★★★★★ ()
Ответ на: комментарий от mashina

Хорошо. Вопрос закрыт. Будем думать с админами - что делать.

pacify ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.