2012-02-16 34 views
5

我在我的python/wsgi web應用程序中遇到問題。每個2個wsgi守護進程中的每個線程都有一個不同的持久mysqldb連接。有時,在刪除舊會話並創建新會話後,某些連接仍然會在選擇中獲取舊會話,這意味着它們無法驗證會話並再次請求登錄。爲什麼有些mysql連接在刪除+插入後選擇舊數據mysql數據庫?

詳細信息:會話存儲在本地mysql數據庫的InnoDB表中。認證後(通過CAS),我刪除該用戶的任何以前的會話,創建一個新的會話(插入一行),提交事務,並重定向到最初請求的頁面,並使用cookie中的新會話ID。對於每個請求,會根據數據庫中的會話檢查Cookie中的會話ID。

有時,在重定向後,數據庫中找不到新創建的會話。相反,該用戶的舊的會話仍然存在。 (我通過在每個請求開始時選擇並記錄所有會話來檢查這一點)。不知何故,我得到緩存的結果。我嘗試用SQL_NO_CACHE選擇會話,但它沒有任何區別。

爲什麼我得到緩存的結果?高速緩存何處可以發生,以及如何停止或刷新高速緩存?基本上,爲什麼其他連接無法看到新插入的數據?

回答

9

MySQL默認爲隔離級別「REPEATABLE READ」,這意味着在事務開始後您不會看到事務中的任何更改 - 即使這些(其他)更改已提交。

如果您在這些會話中發出COMMIT或ROLLBACK,您應該會看到已更改的數據(因爲這會結束正在進行的事務)。

另一個選項是將這些會話的隔離級別更改爲「READ COMMITTED」。也許還有一個選項可以更改默認級別,但是您需要查看相關手冊。

+0

我確實在插入後執行(上面編輯)。你的意思是我也應該在其他連接中提交或回滾? – jmilloy 2012-02-16 20:27:15

+0

是的,你需要結束* other *會話打開的事務(或者改變隔離級別) – 2012-02-16 20:27:49

+0

太棒了,我在每個請求的開頭添加了一個提交,並且這似乎已經起作用。也許最好這樣做,但無論是哪種情況......如果它持續一兩天,我會回來標記這是正確的。 – jmilloy 2012-02-16 20:32:04

2

是的,它看起來像假設你只是執行一個事務,然後斷開連接。如果你有不同的需求,那麼你需要解決這個假設。正如@a_horse_with_no_name所提到的那樣,您可以放入一個提交(儘管如果您實際上沒有更改數據,我會使用回滾)。或者您也可以將光標更改隔離級別 - 從this discussion我用這個:

dbcursor.execute("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")

或者說,它看起來像你可以設置自動提交到真正的連接:

dbconn.autocommit(True)

雖然,如果實際進行連接更改,不建議這樣做。

+1

即使我只是在執行'select's,並且底層表在我的腳本之外被修改,我也必須使用'db.autocommit(True)'。 – thedude 2017-04-18 15:40:35