必须让写入路径具备容错和重试能力:应用层监听主节点状态、事务设为可重放、禁用autocommit、批量控制在500–1000行,并统一max_allowed_packet;sql server alwayson下需正确配置spn和applicationintent,避免kerberos认证失败。

不能靠单点写入来保证高可用,必须让写入路径本身具备容错和重试能力。
写入必须走主节点,但主节点故障时怎么不丢数据
MySQL 集群(如 NDB 或 InnoDB Cluster)和 SQL Server AlwaysOn 的核心约束是一致的:INSERT 只能发往当前 PRIMARY(主)副本。一旦主节点宕机,写入会失败——除非你提前做了两件事:
- 应用层必须监听
WSREP_CLUSTER_STATUS(Percona XtraDB Cluster / Galera)或group_replication_primary_member(InnoDB Cluster)等状态变量,发现主切换后主动重连新主 - 事务必须设为可重放:避免
UUID()、NOW()这类非确定性函数;主键尽量用自增整数而非随机值,否则故障转移后可能因 GTID 或 LSN 不一致导致插入失败 - 不要依赖
autocommit=1:默认自动提交会让单条 INSERT 成为独立事务,主切走时未刷盘的日志就丢了;应显式用START TRANSACTION包裹批量写入,并在收到COMMIT成功响应后再认为写入完成
批量 INSERT 在集群里更容易失败,原因在哪
不是语句本身有问题,而是集群对事务大小和网络延迟更敏感:
-
max_allowed_packet必须在所有节点上统一调大(比如 64M),否则某节点解析INSERT INTO t VALUES (...),(...),...时直接报错Packets larger than max_allowed_packet are not allowed - Galera 和 InnoDB Cluster 要求所有节点对同一事务达成共识,如果一批插入含 5000 行且每行 200 字节,整个事务 binlog event 就超 1MB,网络抖动时容易触发
WSREP: commit failed for reason: 4(即 cert failure) - 建议把每批控制在 500–1000 行以内,并配合
wsrep_causal_reads=ON(Galera)或group_replication_consistency=AFTER(InnoDB Cluster)确保读已提交再继续下一批
SQL Server AlwaysOn 下 INSERT 报错 “The target principal name is incorrect” 怎么解
这是 Kerberos 认证在跨节点重定向时失效的典型表现,不是权限问题:
- 检查 SQL Server 实例是否注册了正确的 SPN:
setspn -L MSSQLSvc/FQDN:1433,FQDN 必须与连接字符串中写的完全一致(比如ag-listener.contoso.com) - 确认客户端连接字符串启用
ApplicationIntent=ReadWrite,否则可能被路由到只读副本并触发认证失败 - 别用
localhost或 IP 连接可用性组监听器——Kerberos 不认 IP,必须用完整域名
真正难处理的是跨数据中心场景:网络延迟超过 50ms 时,同步提交模式下的 INSERT 延迟会陡增,这时得权衡是降级为异步提交(牺牲强一致性),还是改用应用层分片 + 最终一致性补偿。集群本身不解决写入路径的拓扑问题,它只负责故障时不让写挂掉。











