2011-05-09 56 views
21

我的Python程序查詢一組在MySQL數據庫表的,睡30秒,然後再詢問他們,等有問題的表不斷由第三方更新,(顯然)我希望每30秒看到新的結果。慢性陳舊導致的Python

比方說我的查詢看起來像這樣:

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

定期我會看到我的程序停止後的一個或兩個迭代尋找新的結果,即使新行存在的表格中。我知道表中存在新的行,因爲當我從交互式mysql發出相同的查詢(即不是從Python)時,我可以看到它們。

我發現,問題消失在Python,如果我終止每次查詢後我與數據庫的連接,然後建立了一個查詢一個新的。

我想,也許這可能是因爲這裏討論的服務器端緩存的問題:Explicit disable MySQL query cache in some parts of program

但是:

  1. 當我檢查的互動mysql外殼,它說,緩存上。 (所以如果這是一個緩存問題,交互shell怎麼不會受到它的影響?)

  2. 如果我在我的Python程序中明確執行SET SESSION query_cache_type = OFF,問題仍然存在。

爲每個查詢創建一個新的數據庫連接是我能夠使問題消失的唯一方法。

如何從Python獲取我的查詢以查看我知道的新結果?

+1

你不應該使用查詢中的'%'格式運算符。對所有佔位符使用'%s'(不管它們的類型是什麼),並將值傳遞給元組/列表,以便它們可以正確地進行消毒。 – ThiefMaster 2011-05-09 23:01:29

+1

只是一個猜測:確保從數據庫讀取的查詢與事務的其他更改沒有隔離。即在每次讀取之前創建一個新的事務。 – jsw 2011-05-09 23:14:37

+3

@ThiefMaster:'%d'實際上在查詢中是可以的,因爲它強制替換爲整數,不能用於SQL注入攻擊。 – Jonathan 2011-05-10 14:37:51

回答

21

This websitethis website包含在同一個問題的信息。爲了讓你的表保持最新,你必須提交你的交易。使用db.commit()來做到這一點。

正如我在下面的帖子中提到的,您可以通過啓用自動提交功能來刪除對此的需求。這可以通過運行db.autocommit(True)

此外,在交互的shell啓用自動提交完成,所以這就是爲什麼你沒有這個問題存在。

+0

感謝您的提示!這正是問題所在。我想我太習慣甲骨文了。 :) – dg99 2011-05-10 14:28:42

+2

我也受益於此。但你能否解釋爲什麼autocommit可以幫助SELECT語句?我的源代碼(在開發中)是PHPMyAdmin,它總是返回更新後的結果。但是我的Python程序沒有啓用自動提交功能。 – aitchnyu 2011-10-12 05:25:33

+3

我和@aitchnyu有同樣的問題,我的python進程只做'select's。我有一個完全的其他過程來完成寫作,我把'commit()'放在'execute()'之後,並且放在'fetchall()'之前,它就可以工作。這很酷,但你爲什麼要在讀取語句中執行'commit()'? – Landon 2012-11-16 01:03:28

9

可以啓用自動MySQLdb的自動提交!請嘗試以下操作:

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

這給出了您在交互式shell中使用的相同行爲。

+0

還有一個關鍵字參數'autocommit' – 2016-02-04 16:32:32

9

您可能想要檢查數據庫的事務隔離級別。您所描述的行爲如果設置爲REPEATABLE-READ,您可能會期望得到。您可能需要將其更改爲READ-COMMITTED。

既然問題的樓主提到他只是查詢的數據庫,就不能提交該被遺忘。插入一個提交似乎是一種解決方法,儘管它會導致一個新的事務開始;並且可能需要建立新的快照。儘管如此,不得不在每次選擇之前插入一個提交對我來說聽起來並不是很好的編程習慣。

由於解決方案在於正確配置數據庫,因此沒有顯示python代碼。

DO檢查MySQL文檔http://dev.mysql.com/doc/refman/5.5/en/set-transaction.html

REPEATABLE READY
這是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) 

設置事務隔離級別讀取已提交

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> 

並再次運行該應用程序...

+0

A poor回答.. – 5ervant 2013-04-15 07:10:06

+0

說明你回答一些更多的解釋和代碼 – 2013-04-15 07:11:13

+0

檢查MySQL手冊中的事務隔離級別的行爲。 – GuruMatics 2013-04-23 09:28:44