2015-12-07 17 views
6

Trong khối giả này:An toàn để sử dụng unsafeIOToSTM để đọc từ cơ sở dữ liệu?

atomically $ do 
    if valueInLocalStorage key 
     then readValueFromLocalStorage key 
     else do 
     value <- unsafeIOToSTM $ fetchValueFromDatabase key 
     writeValueToLocalStorage key value 

Có an toàn để sử dụng unsafeIOToSTM? Các tài liệu nói:

  • Việc thực hiện STM thường sẽ chạy giao dịch nhiều lần, vì vậy bạn cần phải chuẩn bị cho điều này nếu IO của bạn có bất kỳ tác dụng phụ.

    Về cơ bản, nếu giao dịch không thành công do một số luồng khác wroteValueToLocalStorage và khi giao dịch được thử lại, nó sẽ trả về giá trị đã lưu thay vì tìm nạp lại từ cơ sở dữ liệu.

  • Việc triển khai STM sẽ hủy bỏ các giao dịch được xác định là không hợp lệ và cần phải được khởi động lại. Điều này có thể xảy ra ở giữa không an toànIOToSTM, vì vậy hãy đảm bảo bạn không có bất kỳ tài nguyên nào cần phát hành (trình xử lý ngoại lệ bị bỏ qua khi hủy giao dịch). Điều đó bao gồm làm bất kỳ IO bằng cách sử dụng Handles, ví dụ. Bắt sai này có thể sẽ dẫn đến deadlocks ngẫu nhiên.

    Điều này làm tôi lo lắng nhất. Về mặt logic, nếu fetchValueFromDatabase không mở kết nối mới (tức là kết nối hiện có được sử dụng) mọi thứ sẽ ổn. Có những cạm bẫy khác tôi đang thiếu?

  • Giao dịch có thể đã thấy chế độ xem bộ nhớ không phù hợp khi IO chạy. Các bất biến mà bạn mong đợi là đúng trong suốt chương trình của bạn có thể không đúng trong một giao dịch, do cách thức các giao dịch được thực hiện. Thông thường, điều này sẽ không hiển thị với lập trình viên, nhưng việc sử dụng unsafeIOToSTM có thể hiển thị nó.

    key là một giá trị duy nhất, không có bất biến nào để phá vỡ.

+1

Mục thứ hai thực sự rất đáng sợ. – chi

+0

Tôi có thể hỏi, tại sao bạn muốn làm điều này trong STM? – MathematicalOrchid

+0

@MathematicalOrchid: Tôi có một cửa hàng địa phương/bộ nhớ cache trong một 'TVar'. Bất cứ khi nào một cái gì đó không có trong cửa hàng, nó sẽ được lấy từ cơ sở dữ liệu và được lưu trong cửa hàng. Tôi có thể tất nhiên (và hiện tại) chia nó thành 2 bước: STM (kiểm tra giá trị trong kho) -> IO (lấy từ db) -> STM (lưu trong kho), nhưng điều này có nghĩa là một luồng khác có thể để thay đổi cửa hàng trong cửa sổ giữa hai giao dịch STM. –

Trả lời

3

Tôi khuyên bạn nên thực hiện I/O từ giao dịch STM chỉ là một ý tưởng tồi.

Có lẽ những gì bạn muốn là tránh hai chủ đề thực hiện tra cứu DB cùng một lúc. Những gì tôi sẽ làm là:

  • Xem mục đã có trong bộ nhớ cache chưa. Nếu có, chúng ta đã xong.

  • Nếu không, hãy đánh dấu nó bằng cờ "Tôi đang tìm nạp này", cam kết giao dịch STM, chuyển nó từ DB và thực hiện giao dịch STM thứ hai để chèn nó vào bộ đệm (và loại bỏ cờ).

  • Nếu mặt hàng đã bị gắn cờ, retry giao dịch. Việc này sẽ chặn chuỗi gọi cho đến khi chuỗi đầu tiên chèn giá trị từ DB.

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