2012-02-16 54 views
5

Tôi đang gặp sự cố với các phiên trong ứng dụng web python/wsgi của mình. Có một kết nối mysqldb khác nhau, liên tục cho mỗi luồng trong mỗi 2 quy trình daemon wsgi. Đôi khi, sau khi xóa phiên cũ và tạo phiên mới, một số kết nối vẫn tìm nạp các phiên cũ trong một lựa chọn, điều đó có nghĩa là chúng không xác thực được phiên và yêu cầu đăng nhập lại.Tại sao một số kết nối mysql chọn dữ liệu cũ cơ sở dữ liệu mysql sau khi xóa + chèn?

chi tiết: Sessions được lưu trữ trong một bảng InnoDB trong một cơ sở dữ liệu mysql địa phương. Sau khi xác thực (thông qua CAS), tôi xóa mọi phiên trước đó cho người dùng đó, tạo phiên mới (chèn hàng), cam kết giao dịch và chuyển hướng đến trang được yêu cầu ban đầu với id phiên mới trong cookie. Đối với mỗi yêu cầu, một id phiên trong cookie được kiểm tra đối với các phiên trong cơ sở dữ liệu.

Đôi khi, một phiên mới được tạo ra không tìm thấy trong cơ sở dữ liệu sau khi chuyển hướng. Thay vào đó, phiên cũ cho người dùng đó vẫn còn ở đó. (Tôi đã kiểm tra điều này bằng cách chọn và ghi nhật ký tất cả các phiên ở đầu mỗi yêu cầu). Bằng cách nào đó, tôi nhận được kết quả được lưu trong bộ nhớ cache. Tôi đã thử chọn các phiên với SQL_NO_CACHE, nhưng nó không có sự khác biệt.

Tại sao tôi nhận được kết quả được lưu trong bộ nhớ cache? Nơi nào khác có thể bộ nhớ đệm xảy ra, và làm thế nào có thể ngăn chặn nó hoặc làm mới bộ nhớ cache? Về cơ bản, tại sao các kết nối khác lại không nhìn thấy dữ liệu mới được chèn vào?

Trả lời

9

MySQL mặc định là mức độ cô lập "chế đọc lặp lại" có nghĩa là bạn sẽ không thấy bất kỳ thay đổi trong giao dịch của bạn đã được thực hiện sau khi giao dịch bắt đầu - ngay cả khi những thay đổi (khác) đã được cam kết.

Nếu bạn đưa ra một COMMIT hoặc ROLLBACK trong những phiên giao dịch, bạn sẽ thấy các dữ liệu thay đổi (vì đó sẽ kết thúc giao dịch đó là "cơ bản dở dang").

Các tùy chọn khác là để thay đổi mức độ cô lập đối với những phiên tới "ĐỌC CAM KẾT". Có thể có một tùy chọn để thay đổi mức mặc định là tốt, nhưng bạn sẽ cần phải kiểm tra hướng dẫn cho điều đó.

+0

Tôi cam kết sau khi chèn (chỉnh sửa ở trên). Bạn có nghĩa là tôi cũng nên cam kết hoặc rollback trong các kết nối khác không? – jmilloy

+0

Có, bạn cần kết thúc giao dịch đang mở phiên * khác * (hoặc thay đổi mức cách ly) –

+0

Tuyệt vời, tôi đã thêm một cam kết vào đầu mỗi yêu cầu và dường như đã hoạt động. Có lẽ tốt hơn là làm điều đó vào cuối, nhưng trong cả hai trường hợp ... Tôi sẽ quay lại để đánh dấu điều này là chính xác nếu nó giữ cho một hoặc hai ngày. – jmilloy

2

Vâng, có vẻ như giả định là bạn đang chỉ sẽ thực hiện một giao dịch duy nhất và sau đó ngắt kết nối. Nếu bạn có nhu cầu khác, thì bạn cần phải làm việc xung quanh giả định này. Như đã đề cập bởi @a_horse_with_no_name, bạn có thể đặt trong một cam kết (mặc dù tôi sẽ sử dụng một rollback nếu bạn không thực sự thay đổi dữ liệu). Hoặc bạn có thể thay đổi mức độ cô lập trên con trỏ - từ this discussion Tôi sử dụng này:

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

Hoặc, có vẻ như bạn có thể thiết lập tự động cam kết để thực về các kết nối:

dbconn.autocommit(True)

Mặc dù, một lần nữa, điều này không được khuyến khích nếu thực sự thực hiện các thay đổi trong kết nối.

+1

Tôi đã phải sử dụng 'db.autocommit (True)' ngay cả khi tôi đã chỉ làm 'select's và các bảng cơ bản đã được thay đổi bên ngoài kịch bản của tôi. – thedude

Các vấn đề liên quan