2014-02-08 2 views
2

У меня есть таблица, jobs, с полями id, rank и datetime started в базе данных MySQL InnoDB.проблема обновления параллелизма sqlalchemy

Каждый раз, когда процесс получает задание, он «проверяет», что это задание должно быть отмечено, так что никакой другой процесс не будет работать на нем.

Я хочу, чтобы один процесс с сеансом, чтобы иметь возможность:

  1. Найти работу с наибольшим рейтингом
  2. Update эта работа началась поле с текущей временной меткой

без риска что любая другая сессия также может выбирать и начинать работу с наивысшим рейтингом. Другие сеансы также меняют рейтинг в любой момент времени.

Это моя попытка:

session.execute("LOCK TABLES jobs READ") 
next_job = session.query(Jobs).\ 
    filter(Jobs.started == None).\ 
    order_by(Jobs.rank.desc()).first() 

# mark as started 
smt = update(Jobs).where(Jobs.id == next_job.id).\ 
    values(started=datetime.now()) 
session.execute(smt) 
session.execute("UNLOCK TABLES") 

, но это не удается с:

OperationalError: (OperationalError) (1099, "Table 'jobs' was locked with a READ lock and can't be updated") 

Я бы предпочел, чтобы сделать это в более вещий образом, SQLAlchemy предлагает в любом случае. Как я могу это сделать?


EDIT: Чтобы уточнить, я говорю о читать параллелизм/записи в базе данных, не поточно/синхронизации процесса. Мои работники будут распространяться по сети.

ответ

2

Блокировка таблицы не хорошо. Вы можете заблокировать строку при выборе.

Следующий код использовать with_lockmode(): (? И выручать после 77 попыток)

try: 
    job = session.query(Jobs).with_lockmode('update').filter(
     Jobs.started == None).first() 
    # do something 
    session.commit() 
except Exception as exc: 
    # debugs an exception 
    session.rollback() 

Вы, вероятно, хотите, чтобы поместить его в то время как петли и повторите несколько раз.

+0

метод '.with_update_for()' на самом деле то, что вам нужно использовать. – lollercoaster

+0

'.with_update_for'? Можете ли вы предоставить ссылку на документацию? – Eric

+0

Вы имеете в виду ['with_for_update'] (http://docs.sqlalchemy.org/en/rel_0_9/orm/query.html#sqlalchemy.orm.query.Query.with_for_update) – Eric

-2

Вам нужно будет использовать блокировки python.

Это хороший читать, пожалуйста, смотрите.

http://effbot.org/zone/thread-synchronization.htm

+0

Нет, я говорю о блокировке на уровне базы данных. Мои процессы выполняются на отдельных машинах. Я уточнил этот вопрос. – lollercoaster

Смежные вопросы