Подтвердить что ты не робот

Хронические устаревшие результаты с использованием MySQLdb в Python

Программа My Python запрашивает набор таблиц в БД MySQL, засыпает в течение 30 секунд, затем запрашивает их снова и т.д. Указанные таблицы постоянно обновляются сторонними, и (очевидно) я хотел бы видеть новые результаты каждые 30 секунд.

Скажем, мой запрос выглядит так:

"select * from A where A.key > %d" % maxValueOfKeyFromLastQuery

Регулярно я увижу, что моя программа перестает находить новые результаты после одной или двух итераций, даже если новые таблицы присутствуют в таблицах. Я знаю, что новые строки присутствуют в таблицах, потому что я вижу их, когда я выдаю идентичный запрос из интерактивного mysql (т.е. Не из Python).

Я обнаружил, что проблема пропадает в Python, если я завершаю свое соединение с базой данных после каждого запроса, а затем устанавливаю новый для следующего запроса.

Я подумал, может быть, это может быть проблема кэширования на стороне сервера, как обсуждалось здесь: Явное отключение кеша запросов MySQL в некоторых частях программы

Однако:

  • Когда я проверяю интерактивную оболочку mysql, он говорит, что кеширование включено. (Итак, если это проблема кэширования, как интерактивная оболочка не страдает от нее?)

  • Если я явно выполняю SET SESSION query_cache_type = OFF из моей программы Python, проблема все равно возникает.

Создание нового соединения с БД для каждого запроса - единственный способ, с помощью которого я мог решить проблему.

Как я могу получить свои запросы от Python, чтобы увидеть новые результаты, которые, как я знаю, есть?

4b9b3361

Ответ 1

Этот веб-сайт и этот веб-сайт содержат информацию о той же проблеме. Чтобы обновлять ваши таблицы, вы должны совершать транзакции. Используйте db.commit() для этого.

Как упоминалось в сообщении ниже меня, вы можете устранить необходимость этого, включив автоматическое совершение. это можно сделать, запустив db.autocommit(True)

Кроме того, автоматическая фиксация включена в интерактивной оболочке, поэтому это объясняет, почему у вас не было проблемы.

Ответ 2

Вы можете включить автоматическую фиксацию автоматически в MySQLdb! Попробуйте следующее:

conn = MySQLdb.Connect("host", "user", "password")
conn.autocommit(True)

Это дает вам то же поведение, с которым вы привыкли в интерактивной оболочке.

Ответ 3

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

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

Не существует кода для Python, поскольку решение заключается в правильной настройке базы данных.

DO проверьте документацию MySQL на http://dev.mysql.com/doc/refman/5.5/en/set-transaction.html.

ПОВТОРНОЕ ПРОЧИТАНИЕ
Это уровень изоляции по умолчанию для InnoDB. Для последовательных чтений существует важное отличие от уровня изоляции READ COMMITTED: все согласованные чтения в одной транзакции считывают моментальный снимок, установленный первым чтением. Это соглашение означает, что если вы выдаете несколько простых (неблокирующих) операторов SELECT в рамках одной транзакции, эти операторы SELECT также согласуются друг с другом. См. Раздел 14.3.9.2," Согласованные неблокирующие чтения ".

ЧИТАЙТЕ КОМИТЕТОМ
Уровень изоляции, подобный Oracle, относительно последовательного (неблокирующего) чтения: Каждое последовательное чтение, даже в пределах одной транзакции, устанавливает и считывает собственный свежий снимок. См. Раздел 14.3.9.2, "Согласованные неблокирующие чтения ".

Проверка настроенного уровня изоляции:

>mysql > SELECT @@GLOBAL.tx_isolation, @@tx_isolation;
+-----------------------+-----------------+
| @@GLOBAL.tx_isolation | @@tx_isolation  |
+-----------------------+-----------------+
| REPEATABLE-READ       | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.01 sec)

Установка уровня изоляции транзакций на READ-COMMITTED

mysql> SET GLOBAL tx_isolation='READ-COMMITTED';
Query OK, 0 rows affected (0.00 sec)

mysql> SET SESSION tx_isolation='READ-COMMITTED';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @@GLOBAL.tx_isolation, @@tx_isolation;
+-----------------------+----------------+
| @@GLOBAL.tx_isolation | @@tx_isolation |
+-----------------------+----------------+
| READ-COMMITTED        | READ-COMMITTED |
+-----------------------+----------------+
1 row in set (0.01 sec)

mysql>

И запустите приложение еще раз...