天天看點

Erlang Mnesia 資料丢失(并未真正丢失,隻是索引丢失)

Mnesia 資料丢失(并未真正丢失,隻是索引丢失)

用Mnesia建構的 ws_session,資料讀寫都有用了dirty操作。

系統剛上線沒有出現問題,過了一段時間發現使用者登入出現異常(總結發現都是使用者切換網絡時候出現)。進一步分析發現資料不同步了,例如根據 mnesia:dirty_index_read(ws_session, 2, id) 查資料總是查出空,偶爾在節點上查到資料(後來發現是根據 Key),起初誤以為叢集節點資料不同步。多次試驗後發現 index查不到資料,key 能查到資料,得出結論是索引丢失了,百思不得其解,進一步了解發現是mnesia:dirty_delete_object删除時候隻删除了索引,沒有删除資料。

原來delete_object時候原來record 已被修改過了,才導緻此次删除資料時隻删除了索引,現在看上去比較合理,畢竟隻丢失了索引。

但是更讓人意外的是即使資料重寫也不會再生成索引了,必須先根據 Key 把資料删除。

解決方案,删除資料的時候避免采用 delete_object,改為直接根據 Key 删除。查詢資料時,先根據索引查詢資料,若發現有索引丢失,立馬根據 Key 把資料删除,重新生成一份資料,這樣才能保證生成索引。

手冊中有明确的解釋:

delete_object(Tab, Record, LockKind) -> transaction abort | ok 

If a table is of type bag, it can sometimes be needed to delete only some of the records with a certain key. This can be done with the function delete_object/3. A complete record must be supplied to this function.

The semantics of this function is context-sensitive. For details, see mnesia:activity/4. In transaction-context, it acquires a lock of type LockKind on the record. Currently, the lock types write and sticky_write are supported.
           

繼續閱讀