该方法主要使用在通过迭代的方式下遍历整个的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.