2012-06-15 2 views
2

У меня есть это работает на веб-сайте. Когда пользователь входит в систему, я запрашиваю его профиль, чтобы узнать, сколько «кредитов» он имеет. Кредиты приобретаются через paypal. Если человек покупает кредиты и идет оплата, запрос по-прежнему показывает 0 кредитов, хотя, если я запускаю тот же запрос в phpmyadmin, он приносит правильный результат. Если я перезапущу веб-сервер apache и перезагрузите страницу, отобразится правильное количество кредитов. Вот мой картографа код, который показывает количество кредитов, каждый пользователь имеет:sqlalchemy кеширование некоторых запросов

mapper(User, users_table, order_by = 'user.date_added DESC, user.id DESC', properties = { 
    'userCreditsCount': column_property( 
     select( 
      [func.ifnull(func.sum(orders_table.c.quantity), 0)], 
      orders_table.c.user_id == users_table.c.id 
     ).where(and_( 
      orders_table.c.date_added > get_order_expire_limit(), # order must not be older than a month 
      orders_table.c.status == STATUS_COMPLETED 
     )).\ 
     label('userCreditsCount'), 
     deferred = True 
    ) 
    # other properties.... 
}) 

Я использую SQLAlchemy с рамкой колбы, но не использовать их колбу-SQLAlchemy пакета (только чистый SQLAlchemy)

Вот как я начинаю моя база данных:

engine = create_engine(config.DATABASE_URI, pool_recycle = True) 
metadata = MetaData() 
db_session = scoped_session(sessionmaker(bind = engine, autoflush = True, autocommit = False)) 

Я узнал, как питон и SQLAlchemy в этом проекте, так что я может отсутствовать вещи, но это один сводит меня с ума. Есть идеи?

ответ

0

набор sessionmaker автокоммит «s Истина и посмотреть, если это помогает, согласно документации sessionmaker кэшей

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

так в коде он стал бы:

sessionmaker(bind = engine, autoflush = True, autocommit = True) 
+0

Я не думаю, что автоматическая установка на True - это умный способ. Они даже не рекомендуют его в своих документах. –

2

Пожалуйста, попробуйте позвонить refresh or expire на вашем объекте, прежде чем получить доступ к поле userCreditsCount:

user1 = session.query(User).get(1) 
# ... 
session.refresh(user1, ('userCreditsCount',)) 

Это позволит сделать запрос выполнить снова (когда вызывается обновление).

Однако, в зависимости от режима изоляции, который использует ваша транзакция, он может не решить проблему, и в этом случае вам может потребоваться выполнить/отменить транзакцию (сеанс), чтобы запрос дал вам новый результат.

1

Lifespan of a Contextual Session

Я бы убедиться, что вы закрытия сессии, когда вы сделали с ним.

session = db_session() 
try: 
    return session.query(User).get(5) 
finally: 
    session.close() 
3

при работе с сессии, как только он начинает работать с соединением, он держит на этой связи, пока не совершат(), откат() или закрыть() называется. В DBAPI соединение с базой данных также остается в транзакции до тех пор, пока транзакция не будет совершена или не будет отменена.

В этом случае, когда вы загружали данные в свою сессию, SQLAlchemy не обновляет данные до завершения транзакции (или если вы явно истекаете часть данных с expire()). Это естественное поведение, поскольку из-за transaction isolation очень вероятно, что текущая транзакция не может увидеть изменения, произошедшие с момента начала этой транзакции.

Таким образом, при использовании expire() или refresh() может быть или не быть частью того, как получить последние данные на вашем сеансе, действительно вам нужно прекратить транзакцию и начать новую, чтобы действительно увидеть, что было изменено в другом месте поскольку эта транзакция началась.вы должны организовать свое приложение так, чтобы конкретный Session() был готов к работе, когда приходит новый запрос, но когда этот запрос завершается, Session() должен быть закрыт, а новый (или, по крайней мере, новая транзакция) запущен по следующему запросу.

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