From e2f4a627dbadf214af09d771d15f91e138392c88 Mon Sep 17 00:00:00 2001 From: Shawn <506895667@qq.com> Date: Tue, 12 May 2026 14:37:53 +0800 Subject: [PATCH] revert: #263 and #264 We don't need to check where was the table loaded from, since we have fixed the problem in OTP-24.3.4.17-1 --- src/ekka.appup.src | 2 + src/ekka_mnesia.erl | 114 +------------------------------------ test/ekka_mnesia_SUITE.erl | 6 +- 3 files changed, 4 insertions(+), 118 deletions(-) diff --git a/src/ekka.appup.src b/src/ekka.appup.src index f5751bcd..e7c7c2c6 100644 --- a/src/ekka.appup.src +++ b/src/ekka.appup.src @@ -3,6 +3,7 @@ {VSN, [{"0.8.1.17", [{load_module,ekka_cluster,brutal_purge,soft_purge,[]}, + {load_module,ekka_mnesia,brutal_purge,soft_purge,[]}, {load_module,ekka_autoheal,brutal_purge,soft_purge,[]}]}, {"0.8.1.16", [{load_module,ekka_cluster,brutal_purge,soft_purge,[]}, @@ -142,6 +143,7 @@ {load_module,ekka_dist,brutal_purge,soft_purge,[]}]}], [{"0.8.1.17", [{load_module,ekka_cluster,brutal_purge,soft_purge,[]}, + {load_module,ekka_mnesia,brutal_purge,soft_purge,[]}, {load_module,ekka_autoheal,brutal_purge,soft_purge,[]}]}, {"0.8.1.16", [{load_module,ekka_cluster,brutal_purge,soft_purge,[]}, diff --git a/src/ekka_mnesia.erl b/src/ekka_mnesia.erl index a5409bbb..4536239c 100644 --- a/src/ekka_mnesia.erl +++ b/src/ekka_mnesia.erl @@ -310,119 +310,7 @@ wait_for(stop) -> wait_for(tables) -> Tables = mnesia:system_info(local_tables), - case do_wait_for_tables(Tables) of - {error, _} = Error -> - Error; - ok -> - case mnesia:system_info(db_nodes) -- [node()] of - [] -> ok; - _OtherDBNodes -> - case ekka:env(skip_table_load_check, false) of - true -> - logger:warning("Skipping table load origin check because " - "'skip_table_load_check' is set to true. " - "This may hide data inconsistency issues, " - "please unset this option after the node is up."), - ok; - false -> - %% Make sure we have loaded tables from a remote node, - %% or force-loaded from local copies by the user. - RemoteActiveReplicas = get_remote_active_replicas(), - case check_tables_load_from(Tables, RemoteActiveReplicas) of - ok -> ok; - {error, _} = Error -> Error - end - end - end - end. - -check_tables_load_from([], _) -> - ok; -check_tables_load_from([schema | Rest], RemoteActiveReplicas) -> - check_tables_load_from(Rest, RemoteActiveReplicas); -check_tables_load_from([Tab | Rest], RemoteActiveReplicas) -> - LoadFrom = mnesia_lib:val({Tab, load_node}), - LoadReason = mnesia_lib:val({Tab, load_reason}), - case mnesia:table_info(Tab, local_content) of - true -> - check_tables_load_from(Rest, RemoteActiveReplicas); - false -> - Self = node(), - RemoteReplicas = get_remote_replicas(Tab), - case {LoadFrom, RemoteReplicas, RemoteActiveReplicas} of - {Self, [], _} -> - %% we have no remote replica - check_tables_load_from(Rest, RemoteActiveReplicas); - {Self, [_ | _], []} -> - %% we have one or more remote replicas but we are loaded from local, - %% maybe force loaded by the user, as we have no active replicas other than current node. - logger:warning( - "Mnesia loaded table ~p from local copy while remote replicas ~p " - "exist but none are active (load_reason=~p). " - "If you have intentionally force-loaded this table (e.g. after removing " - "remote nodes from the cluster), this warning can be safely ignored. " - "Otherwise, please check the network connectivity between cluster nodes, " - "ensure remote nodes are reachable, and restart EMQX.", - [Tab, RemoteReplicas, LoadReason]), - check_tables_load_from(Rest, RemoteActiveReplicas); - {Self, [_ | _], [_ | _]} -> - %% prevent the current node from starting as the table is loaded from local and there - %% are other active replicas in the cluster - logger:error( - "Mnesia loaded table ~p from local copy while remote active replicas ~p " - "are available (load_reason=~p). " - "This is likely caused by a network partition or misconfiguration. " - "The node refuses to start to prevent data inconsistency. " - "Please fix the network connectivity between cluster nodes and restart EMQX.", - [Tab, RemoteActiveReplicas, LoadReason]), - {error, {tab_loaded_from_local_copy, Tab, LoadReason}}; - {Self, unknown, _} -> - logger:error( - "Mnesia loaded table ~p from local copy but this table only resides " - "on remote nodes (load_reason=~p). " - "This is likely caused by a network partition during startup. " - "Please fix the network connectivity between cluster nodes and restart EMQX.", - [Tab, LoadReason]), - {error, {tab_loaded_from_local_copy, Tab, LoadReason}}; - {_, _, _} -> - check_tables_load_from(Rest, RemoteActiveReplicas) - end - end. - -%% @doc Get the remote nodes that are running emqx. -%% -%% Q: Why not use mnesia:table_info(Tab, active_replicas) -- [Self]? -%% A: Because it will cause a deadlock when all other nodes are restarting and waiting for -%% this node to start. -get_remote_active_replicas() -> - RunningNodes = ekka_mnesia:running_nodes() -- [node()], - Result = erpc:multicall(RunningNodes, application, which_applications, [], 5000), - Zip = lists:zip(RunningNodes, Result), - lists:filtermap( - fun - ({Node, {ok, Applications}}) -> - case lists:keymember(emqx, 1, Applications) of - true -> - {true, Node}; - false -> - false - end; - ({_, {error, _}}) -> - false - end, - Zip - ). - -get_remote_replicas(Tab) -> - case mnesia:table_info(Tab, storage_type) of - unknown -> - unknown; - _ -> - RamCopies = mnesia:table_info(Tab, ram_copies), - DiscCopies = mnesia:table_info(Tab, disc_copies), - DiscOnlyCopies = mnesia:table_info(Tab, disc_only_copies), - lists:usort((RamCopies ++ DiscCopies ++ DiscOnlyCopies) -- [node()]) - end. + do_wait_for_tables(Tables). do_wait_for_tables(Tables) -> case mnesia:wait_for_tables(Tables, 30000) of diff --git a/test/ekka_mnesia_SUITE.erl b/test/ekka_mnesia_SUITE.erl index 6f2e0932..68aef90e 100644 --- a/test/ekka_mnesia_SUITE.erl +++ b/test/ekka_mnesia_SUITE.erl @@ -141,11 +141,7 @@ t_diagnosis_tab(_)-> %% Start mnesia on N2. ok = rpc:call(N2, ekka_mnesia, start, []), - %% Restart mnesia on N1 so it loads the table from N2 - %% instead of keeping the stale local copy. - %% (check_tables_load_from rejects locally-loaded tables - %% when remote active replicas exist.) - stopped = rpc:call(N1, mnesia, stop, []), + %% Start ekka_mnesia on N1, no blocking ok = rpc:call(N1, ekka_mnesia, start, []), %% Check tables are loaded on two