Уведомления

Группа в Telegram: @pythonsu

#1 Янв. 21, 2015 14:09:09

Red_Dragon
Зарегистрирован: 2015-01-21
Сообщения: 2
Репутация: +  0  -
Профиль   Отправить e-mail  

Асинхронные запросы для одной таблицы.

Есть небольшой скрип работы с БД:

import json
import collections
import pymysql
cnx = pymysql.connect(user='root', passwd='***',
                      host='127.0.0.1',
                      db='***')
def update_stats(user, link):
    if link == True:
        stats_template = (
            "INSERT INTO stats (user) VALUES(%(userPar)s) ON DUPLICATE KEY UPDATE  messages=messages+1, links=links+1")
    else:
        stats_template = (
            "INSERT INTO stats (user) VALUES(%(userPar)s) ON DUPLICATE KEY UPDATE messages=messages+1")
    stats_data = {
        'userPar': user,
    }
    try:
        cursor_insert = cnx.cursor()
        cursor_insert.execute(stats_template, stats_data)
    except pymysql.Error as e:
        print("Error %d: %s" % (e.args[0], e.args[1]))
    finally:
        cursor_insert.close()
def get_all():
    try:
        cursor_get = cnx.cursor()
        cursor_get.execute("SELECT * FROM stats")
        rows = cursor_get.fetchall()
    except pymysql.Error as e:
        print("Error %d: %s" % (e.args[0], e.args[1]))
    finally:
        cursor_get.close()
    objects_list = []
    for row in rows:
        d = collections.OrderedDict()
        d['user'] = row[0]
        d['messages'] = row[1]
        d['links'] = row[2]
        objects_list.append(d)
    return json.dumps(objects_list)

update_stats и get_all вызываются из разных потоков, то есть могут быть вызваны и одновременно. Ожидал, что если таблица заблокирована одним запросом, то другой будет просто ожидать, но что-то пошло не так. Иногда получаю такое:
File "C:\PythonTools\Python34\lib\site-packages\websocket\_app.py", line 211, in _callback
    callback(self, *args)
  File "C:/Users/user/PycharmProjects/untitled/WS.py", line 9, in on_message
    analysis.string_to_json(message)
  File "C:\Users\user\PycharmProjects\untitled\analysis.py", line 15, in string_to_json
    db_operations.update_stats(user, linksBool)
  File "C:\Users\user\PycharmProjects\untitled\db_operations.py", line 25, in update_stats
    cursor_insert.execute(stats_template, stats_data)
  File "C:\PythonTools\Python34\lib\site-packages\pymysql\cursors.py", line 135, in execute
    result = self._query(query)
  File "C:\PythonTools\Python34\lib\site-packages\pymysql\cursors.py", line 274, in _query
    conn.query(q)
  File "C:\PythonTools\Python34\lib\site-packages\pymysql\connections.py", line 714, in query
    self._affected_rows = self._read_query_result(unbuffered=unbuffered)
  File "C:\PythonTools\Python34\lib\site-packages\pymysql\connections.py", line 865, in _read_query_result
    result.read()
  File "C:\PythonTools\Python34\lib\site-packages\pymysql\connections.py", line 1068, in read
    self._read_result_packet(first_packet)
  File "C:\PythonTools\Python34\lib\site-packages\pymysql\connections.py", line 1108, in _read_result_packet
    self._get_descriptions()
  File "C:\PythonTools\Python34\lib\site-packages\pymysql\connections.py", line 1181, in _get_descriptions
    field = self.connection._read_packet(FieldDescriptorPacket)
  File "C:\PythonTools\Python34\lib\site-packages\pymysql\connections.py", line 829, in _read_packet
    packet = packet_type(buff, self.encoding)
  File "C:\PythonTools\Python34\lib\site-packages\pymysql\connections.py", line 363, in __init__
    self.__parse_field_descriptor(encoding)
  File "C:\PythonTools\Python34\lib\site-packages\pymysql\connections.py", line 373, in __parse_field_descriptor
    self.org_table = self.read_length_coded_string().decode(encoding)
  File "C:\PythonTools\Python34\lib\site-packages\pymysql\connections.py", line 321, in read_length_coded_string
    length = self.read_length_encoded_integer()
  File "C:\PythonTools\Python34\lib\site-packages\pymysql\connections.py", line 302, in read_length_encoded_integer
    c = ord(self.read(1))
  File "C:\PythonTools\Python34\lib\site-packages\pymysql\connections.py", line 258, in read
    raise AssertionError(error)
Error 2014: Command Out of Sync

Похоже, если таблица заблокирована одним запросом, то другой просто выдает ошибку.
Пробовал офф драйвер для MySql, сейчас перешел на pymysql, результат тот-же.
Питон не мой основной язык на котором я пишу, так что решая эту проблему могу пойти по ложному пути. Посоветуйте как решить эту проблему правильно?

Отредактировано Red_Dragon (Янв. 21, 2015 14:10:08)

Офлайн

#2 Янв. 21, 2015 14:15:45

4kpt_III
Зарегистрирован: 2014-12-22
Сообщения: 999
Репутация: +  39  -
Профиль   Отправить e-mail  

Асинхронные запросы для одной таблицы.

Red_Dragon
Питон не мой основной язык на котором я пишу, так что решая эту проблему могу пойти по ложному пути.

Писать на основном языке

Ну а если серьезно - ОРМ.

Офлайн

#3 Янв. 21, 2015 14:21:33

Red_Dragon
Зарегистрирован: 2015-01-21
Сообщения: 2
Репутация: +  0  -
Профиль   Отправить e-mail  

Асинхронные запросы для одной таблицы.

4kpt_III
Ну а если серьезно - ОРМ.
А другой путь? Не хочется использовать ORM ради пары простых запросов.

Офлайн

#4 Янв. 21, 2015 15:58:24

4kpt_III
Зарегистрирован: 2014-12-22
Сообщения: 999
Репутация: +  39  -
Профиль   Отправить e-mail  

Асинхронные запросы для одной таблицы.

Да ну какая разница. Используйте его просто для подключения к БД. С алхимией можно работать тремя путями. Один из которых предполагает использовать ее просто как коннектор к БД.

Офлайн

#5 Янв. 22, 2015 05:23:43

PooH
От:
Зарегистрирован: 2006-12-05
Сообщения: 1948
Репутация: +  72  -
Профиль   Отправить e-mail  

Асинхронные запросы для одной таблицы.

Вы упомянули про потоки, я подозреваю что вы используете одно соединение для всех потоков и проблема не в базе, а в том что один поток пытается выполнить команду, пока другой еще не очистил буфер(я не смотрел внутренности pymysql, чисто интуитивно). Может попробовать создать пул соединений и потокам брать оттуда свободные и возвращать после обработки?

ЗЫ: для быстрой проверки предположения, просто попробуйте создавать в каждом потоке новое подключение, если заработает переходите на пул



Вот здесь один из первых отарков съел лаборанта. Это был такой умный отарк, что понимал даже теорию относительности. Он разговаривал с лаборантом, а потом бросился на него и загрыз…

Отредактировано PooH (Янв. 22, 2015 05:25:28)

Офлайн

#6 Янв. 22, 2015 05:40:48

terabayt
От: Киев
Зарегистрирован: 2011-11-26
Сообщения: 1099
Репутация: +  103  -
Профиль   Отправить e-mail  

Асинхронные запросы для одной таблицы.

txMySQL



————————————————
-*- Simple is better than complex -*-

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version