我们有一个在 WildFly 8.2 和 MariaDB 10 上运行的 Java Web 应用程序。我们目前正在评估从单个 MariaDB 服务器迁移到使用 HAProxy 1.5 作为负载均衡器的三节点 Galera/MariaDB 集群。
当仅针对集群发出 DML 命令时,一切正常。但是在某些情况下,我们的 Java 应用程序会运行 DDL 命令,例如 CREATE TABLE 或 ALTER TABLE。例如,在 Web 界面中可以创建新客户。任何这样的客户都会获得 50 个新表来存储其数据。
假设我们添加 id 为 123 的客户,应用程序将运行以下 DDL 和 DML 查询组合:
-- start customer creation
create table Table1_123 (id int not null,.., primary key (id));
create table Table2_123 (id int not null, tid int not null,..., primary key (id));
....
alter table Table2_123 add constraint constraintName foreign key (tid) references Table1_123 (id);
...
insert into Table1_123 ...; -- insert one or more values
insert into Table2_123 ...; -- insert one or more values
...
-- define tables and insert data up to Table50_123
我们有 wsrep_osu_method=toi(默认值)。
创建这样的客户后,我检查了新创建的表,并且很多时候我发现节点之间存在不一致。表格本身已正确复制,但内容未正确复制。某些节点上的一些新表包含尚未复制到其他节点的数据。
我做了一些测试,只将 Java 应用程序直接连接到单个节点,避免了 HA 代理。我遇到了同样的不一致,但不同之处在于只有应用程序直接连接到的节点才保存未复制的数据。在之前的测试中,未复制的数据分散在所有节点上。
我不明白这种行为。我在日志中没有得到任何相关错误。
运行此类 DDL 查询是经常发生的事情。当然,我们希望自动而不是手动完成。当应用程序运行 DDL 和 DML 时,这种情况的最佳方法是什么?
我们的优先事项如下(按此顺序):
在 DDL 运行期间和之后保持一致性。
在应用程序代码中做最少的更改。
如果可能,自动而不是手动运行 DDL。