該方法主要使用在通過迭代的方式下遍歷整個的ets數據
- 如使用ets:next()或者ets:match_object方法或者ets:select方法迭代的遍歷整個ets數據
作用
- 如果出現數據的刪除,可以平滑的處理這些迭代器的使用,不至於因爲刪除而導致的迭代報錯
- 即使設置了ets:safe_fixtable(Tab, true)也是可以在另外一個進程刪除數據,並且刪除也是有效的
- 注意一旦設置了之後也要設置回ets:safe_fixtable(Tab, false)
erlang網站信息翻譯
- 刪除一個正在fixed的ets對象,他是不是立刻釋放內存的,直到進程釋放了這個fix。並且如果加了fix操作,則table的性能會明顯的變慢。
- 可以使用info(Tab, safe_fixed_monotonic_time)來展示進程fix的table信息。如果多個進程都在fix table則需要報警,或者fix table過長時間,也需要報警。
- 對於ordered_set類型的ets,以及一次性全部讀取的數據,則沒有必要加載fix table
- 一個進程fixtable,則這個table會一直fix,直到進程主動的釋放或者進程關閉。
測試點
- 不添加safe_fixtable,在迭代ets時,添加ets數據,有時會展示在迭代中,有些事不能展示在迭代中
- 不添加safe_fixtable,在迭代ets時,刪除ets數據,回導致迭代報錯
- 不添加safe_fixtable,在迭代ets時,修改ets的原有數據,可以展示最新的數據
- 添加safe_fixtable時,在迭代ets時,添加ets數據,有時會展示在迭代中,有些是不能展示在迭代中
- 添加safe_fixtable時,在迭代ets時,刪除ets數據,可以正常迭代完成,迭代中不會包含刪除的信息
- 添加safe_fixtable時,在迭代ets時,修改ets的原有數據,可以展示最新的數據
不加safe_fix的報錯信息
測試代碼
%% 當前的代碼註釋了safe_fixtable,則會出現迭代調用報錯
%% 放開safe_fixtable之後,則迭代正常,跳過了刪除的數據信息,可以正常的執行完迭代,'$end_of_table'返回
-record(map, {
id = 0, %% 地圖編號id,每個副本唯一
map_id = 0, %% 基礎地形圖id
map_cell = [] %% 地圖標記 [#map_cell{}]
}).
test_ets_fix_up() ->
ets:delete(ets_fix_up),
ets:new(ets_fix_up, [{keypos, #map.id},named_table, public, set]),
ets:insert(ets_fix_up,
[#map{id = 1, map_id = 1111,map_cell = [111111]},
#map{id = 2, map_id = 222,map_cell = [111111]},
#map{id = 3, map_id = 333,map_cell = [111111]},
#map{id = 4, map_id = 4444,map_cell = [111111]}]
),
spawn(
fun() ->
%% ets:safe_fixtable(ets_fix_up, true),
Key = ets:first(ets_fix_up),
io:format("111111 key = ~p ~n", [Key]),
timer:sleep(3000),
Key1 = ets:next(ets_fix_up, Key),
io:format("22222 key1 = ~p ~n", [Key1]),
timer:sleep(3000),
Key2 = ets:next(ets_fix_up, Key1),
io:format("333333 key2 = ~p ~n", [Key2]),
timer:sleep(3000),
Key3 = ets:next(ets_fix_up, Key2),
io:format("444444 key3 = ~p ~n", [Key3]),
timer:sleep(3000),
Key4 = ets:next(ets_fix_up, Key3),
io:format("555555 key4 = ~p ~n", [Key4]),
timer:sleep(3000)
%% ets:safe_fixtable(ets_fix_up, false)
end),
spawn(
fun() ->
timer:sleep(2000),
%% ets:delete(ets_fix_up,2),
ets:insert(ets_fix_up, #map{id = 2, map_id = 1111,map_cell = [111111]}),
ets:insert(ets_fix_up, #map{id = 3, map_id = 1111,map_cell = [111111]}),
io:format("spawn2 = del= ~p ~n", [2]),
%% ets:delete(ets_fix_up,3),
io:format("spawn2 6s del = ~p ~n", [3])
end),
ok.