ent M2M模型在pxc集群中的一个大坑

事故简要分析

PXC集群3个节点,在插入数据时,如果使用数据库自己生成的主键,一般顺序为1,4,7,10…

这里就是坑的源头,在ent底层代码中,在做M2M模型插入时,会先插入两个模型,再插入中间表。即,假设M2M模型为group和user(https://entgo.io/docs/schema-edges#m2m-two-types),这里数据库会产生3张表,users, groups 和 user_groups,其中user_groups存放userid和groupid,这样就组成了一个多对多模型。

事故复原

假设先插入一个group,再插入一堆user,而在使用ent的CreateBulk插入user时,问题就发生了,我们在测试环境永远无法复现出问题,而只要一上生产环境,问题必然出现。原因就在于测试环境使用单节点mysql,生产环境使用的pxc集群!

先看插入代码:

// Add Group
hub := client.Group.
Create().
SetName("GitHub").
SaveX(ctx) // Add Users
bulk := make([]*User, len(users))
for i, user:= range users {
bulk[i] = client.User.
Create().
SetAge(30).
SetName("a8m").
AddGroups(hub)
}
_, err = client.User.CreateBulk(bulk...).Save(ctx)
if err != nil {
return errors.Wrap(err, "User.CreateBulk") // pxc集群必然报错
}

源码分析

.Save()中调用了BatchCreate,又跳转nodes

nodes中主要两行代码是batchInsert和batchAddM2M,直观理解就是,先插入users,在插入user_groups,而插入user_groups时需要拿到所有users的id,由于我们是在一个事务里完成的,因此实际数据并未真正插入,因此ent做了一个看起来没问题的骚操作。

从batchInsert到c.insertLastIDs

重点来了,MySQL数据库id的处理结果是插入一条,剩下的数据加1,这是理想情况。比如插入时,第一条user的id是4,那剩下的id就是5,6,7,8,9…,但实际上,pxc集群处理时并不是这样,因此造成插入users时,id实际是4,7,10,13…,因此最终执行M2M插入操作时报错:add m2m edge for table

正确的应该是1,4 1,7。于是报错:Error 1452: FOREIGN KEY constraint failed

解决方式

PXC集群下

  • 能不用M2M就不用M2M。M2M改O2M;
  • 必须使用M2M时,不使用CreateBulk。该批量为单条;
  • 必须使用CreateBulk时,手动指定id。自行使用分布式id。

ent M2M模型在pxc集群中的一个大坑的更多相关文章

  1. 集群: 如何在spring 任务中 获得集群中的一个web 容器的端口号?

    系统是两台机器, 跑四个 web 容器, 每台机器两个容器 . nginx+memcached+quartz集群,web容器为 tomcat . web 应用中 用到spring 跑多个任务,任务只能 ...

  2. 02使用java脚本向Pxc集群写入数据

    使用java脚本向Pxc集群写入数据 批量写入pxc集群程序 导入mysql驱动包 # 批量插入数据的java脚本 package pxc_demo; import java.sql.Connecti ...

  3. docker swarm英文文档学习-8-在集群中部署服务

    Deploy services to a swarm在集群中部署服务 集群服务使用声明式模型,这意味着你需要定义服务的所需状态,并依赖Docker来维护该状态.该状态包括以下信息(但不限于): 应该运 ...

  4. PXC集群资料整理

    1.mysql集群方案对比 方案1  NDBCluster  参考:https://www.cnblogs.com/kevingrace/p/5685371.html?utm_source=itdad ...

  5. MySQL之PXC集群搭建

    一.PXC 介绍 1.1 PXC 简介 PXC 是一套 MySQL 高可用集群解决方案,与传统的基于主从复制模式的集群架构相比 PXC 最突出特点就是解决了诟病已久的数据复制延迟问题,基本上可以达到实 ...

  6. 对比PXC集群与主从架构在一致性上的区别

    在上一篇文章中,已经完成了三节点PXC集群的搭建,现在搭建node3的从库node4,并且有如下测试: 搭建node3的从库,代号node4 测试1: 先断开node3节点,然后在node1构造数据, ...

  7. MySQL数据库高可用集群搭建-PXC集群部署

    Percona XtraDB Cluster(下文简称PXC集群)提供了MySQL高可用的一种实现方法.集群是有节点组成的,推荐配置至少3个节点,但是也可以运行在2个节点上. PXC原理描述: 分布式 ...

  8. 将自己写的windows服务加入到windows集群中

    最近发现windows集群能进行很多自定义,比如在集群中加入自己编写的服务. 能自定义的可不少,截个图: 本次演示中,只想用“通用服务”这个类型. 先列下步骤 编写一个记录时间的Windows服务,这 ...

  9. Storm集群中执行的各种组件及其并行

    一.Storm中执行的组件      我们知道,Storm的强大之处就是能够非常easy地在集群中横向拓展它的计算能力,它会把整个运算过程切割成多个独立的tasks在集群中进行并行计算.在Storm中 ...

  10. Docker Swarm集群中部署Traefik负载均衡器

    一.创建单节点的Docker Swarm集群 docker swarm init 二.在Swarm集群中创建一个网络 docker network create --driver=overlay tr ...

随机推荐

  1. Less-7 '))闭合 和 secure_file_priv 配置写入一句话木马

    Less-7使用的文件导出select ... into outfile ....,一个文件上传. mysql安全配置里有一个配置secure_file_priv控制文件的导出导入. secure_f ...

  2. python渗透测试入门——Scapy库

    Scapy 是一个用来解析底层网络数据包的Python模块和交互式程序,该程序对底层包处理进行了抽象打包,使得对网络数据包的处理非常简便.该类库可以在在网络安全领域有非常广泛用例,可用于漏洞利用开发. ...

  3. 在wxpython框架写的GUI中调用GIF格式图片,显示在指定行列的方法

    #首先需要从 wx.adv 模块导入 Animation, AnimationCtrl方法 from wx.adv import Animation, AnimationCtrl #然后在面板实现过程 ...

  4. Springboot 结合 Netty 实战聊天系统

    音视频技术为什么需要微服务 微服务,英文名:microservice,百度百科上将其定义为:SOA 架构的一种变体.微服务(或微服务架构)是一种将应用程序构造为一组低耦合的服务. 微服务有着一些鲜明的 ...

  5. Eclipse安装和配置环境教程(图文详解)

    前言 在上一篇文章中,壹哥给大家介绍了Notepad++这个更高级点的记事本,它进行Java开发相比windows自带的记事本要更方便一些.但是即便如此,用这种记事本进行Java开发效率依然很低.如果 ...

  6. Unity JobSystem使用及技巧

    什么是JobSystem 并行编程 在游戏开发过程中我们经常会遇到要处理大量数据计算的需求,因此为了充分发挥硬件的多核性能,我们会需要用到并行编程,多线程编程也是并行编程的一种. 线程是在进程内的,是 ...

  7. v-model 和 .sync

    v-model的本质是父子组件间的通讯,父组件给子组件传递一个value自定义属性和input自定义事件:子组件接收value 并触发自定义事件修改value 父组件中 <Child v-mod ...

  8. MySQL事务还没提交,Canal就能读到消息了?

    [问题描述] 开发有天碰到一个很奇怪的问题,他的场景是这样子的: 通过Canal来订阅MySQL的binlog, 当捕获到有数据变化时,回到数据库,反查该数据的明细,然后做进一步处理. 有一次,他碰到 ...

  9. vue中的v-model 与 .sync

    <input v-model="parentData"> //等同于 <input :value="parentData" @input=&q ...

  10. 多态 polymorphic

    多态是同一个行为具有多个不同表现形式,多态实现需要以下条件 继承父类并重写方法 父类引用指向子类对象:Animal a = new Cat(); 多态实例: //测试类 public class Te ...