Форум сайта python.su
Решил, чтобы лишних проблем не было при работе с потоками всю работу с данными переложить на MySQL. В итоге, во много потоков шлю запросы SELECT и INSERT, буквально подряд, сервер выдает MySQL has gone away. Так и должно быть или я где-то накосячил? Подскажите, как решить проблему.
Офлайн
Проверьте, что все запросы шлются в одном и том же соединении.
Офлайн
LexanderДа вроде так и делаю:
Проверьте, что все запросы шлются в одном и том же соединении.
class Parser(threading.Thread):
def __init__(self,config):
threading.Thread.__init__(self)
self.config = config
def run(self):
while True:
try: item = queue.get_nowait()
except: break
try: self.posting(item)
except: traceback.print_exc()
time.sleep(0.5)
queue.task_done()
def append_to_base(self,links):
#with mutex:
for link in links:
#print link
link = link.replace("&","&")
if not "http"==link[:4]: continue
o = urlparse(link)
host = o.netloc
query = "SELECT * FROM main WHERE LOCATE('{0}',link);".format(esc_str(host))
self.db.query(query)
if not self.db.store_result().num_rows():
print link,"has been added."
query = "INSERT INTO main (link,status) VALUES('{0}','{1}')".format(esc_str(link),0)
self.db.query(query)
def posting(self,row):
t_id,link,status = row[0]
print link,"start."
url = link
post = Post()
the_page = post.get(url)
for regex in self.regulars:
if not the_page: continue
links = re.findall(regex,the_page)
self.append_to_base(links)
#with mutex:
query = "UPDATE main set status='1' where id='{0}';".format(t_id)
self.db.query(query)
def main():
config = ConfigParser.RawConfigParser()
config.read('settings.cfg')
threads = int(config.get("Basic","threads"))
regulars = [x.strip() for x in open(config.get("Basic","regulars"))]
args = dict(config.items('MySQL'))
db = _mysql.connect(host=args['host'], user=args['user'], passwd=args['passwd'], db=args['db'])
while True:
query_string = "SELECT * FROM main WHERE status='0' LIMIT 0,1000;"
db.query(query_string)
res = db.store_result()
if res.num_rows()<1:break
for i in xrange(res.num_rows()):
queue.put(res.fetch_row()) # заносим данные в очередь
#break
for i in xrange(threads):
t = Parser(config) # создаем нить
t.db = db
t.regulars = regulars
t.start() # стартуем
time.sleep(0.1)
queue.join()
print "Next round"
print "Done"
if __name__ == '__main__':
main()
Офлайн
Видимо как раз наоборот надо, чтобы все запросы слались в разных соединениях. Перенес _mysql.connect в конструктор - заработало.
Офлайн
Так у вас все запросы к одной и той же таблице!
Похоже, Мускул просто затыкается от потока запросов в одном соединении.
Вы временно решили проблему, переложив ограничение с одного уровня на другой - повыше.
Точно также есть ограниение на макс. количество соединений и в один прекрасный момент некоторые соединения просто будут отвергаться сервером.
Кроме того, установка соединения - это все таки достаточно дорогая операция для сервера.
Я бы все копал в сторону настроек сервера БД (зависит от желаза) или все же изменил алгоритм.
Зачем здесь потоки, если все операции идут с одной таблицей?
Они ведь все равно упираются в производительность сервера БД.
Офлайн
Потоки нужны для быстрого парсинга, не для работы с таблицей.
То есть оптимальным решением будет поставить блокировки при работе с таблицей? По-моему я так даже пробовал, но точно не помню. Сейчас проблема немножко другая - сервер ложится при 70к записях, как можно это предотвратить не подскажете?
Отредактировано (Июнь 3, 2011 20:52:00)
Офлайн
plusplusЕсли результат парсинга сохраняется в одной и той же таблице, то я вам гарантирую - это и есть узкое место.
Потоки нужны для быстрого парсинга, не для работы с таблицей.
plusplusЭто от многих вещей зависит: начиная от мощности железа и заканчивая настройками Мускула.
Сейчас проблема немножко другая - сервер ложится при 70к записях, как можно это предотвратить не подскажете?
Офлайн