首页 > 其他分享 >ent M2M模型在pxc集群中的一个大坑

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

时间:2023-05-18 22:35:33浏览次数:42  
标签:插入 M2M ent user pxc id

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
Untitled

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

从batchInsert到c.insertLastIDs
Untitled 2

重点来了,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
Untitled 3

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

解决方式

PXC集群下

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

标签:插入,M2M,ent,user,pxc,id
From: https://www.cnblogs.com/insignificant-ru/p/17413474.html

相关文章

  • Sentinel基本使用与源码分析
    系列文章目录和关于我一丶什么是SentinelSentinel官网Sentinel是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。流量整形:限制流......
  • CentOS 7 安装 WordPress
    参考0:https://blog.csdn.net/abcd5711664321/article/details/122554412参考1:https://www.yii666.com/article/551970.html参考2:https://www.cnblogs.com/yanans/p/12945001.html  修改文件/etc/httpd/conf/httpd.conf(一行不改也可以) 一行不改,原来是这样的   ......
  • 使用sockjs-client 和 @stomp/stompjs 创建socket,断线重连机制
    importSockClientfrom'sockjs-client'constStomp=require('@stomp/stompjs')//方法createStompClient(){constthat=thisconstws=newSockClient(`/socket/api/socket-mq?access_token=${getToken()}`)this.stom......
  • centos7部署playwright
    首先可以确定,playwright在centos上部署官方是不支持的,github上可以看到https://github.com/microsoft/playwright/issues/9194   走过很多坑,总结了下面一套部署方案: 一、首先安装比较低的版本#安装playwrightpipinstallplaywright==1.16.1-ihttp://pypi.douba......
  • “Present & Prospects (时局与前瞻) ”
    俗话说:“要富口袋先富脑袋,脑袋决定口袋”现实告诉我们,相比智商,人与人的差距很大一部分是由前瞻视野和思维因素拉开的。思维是无形的,却可以创造出有形的价值。“千金买居,万金买邻”,圈层之道,才是高端人居的终极要”。据斯坦福研究中心发表的一份调查报告指出:一个人赚的钱,12.5%来自......
  • 路由导航报错:NavigationDuplicated: Avoided redundant navigation to current locati
    跳转页面时候,重复点击菜单引起路由重复报错;点击按钮跳转到同一个或当前的路径会报错。为每一个Promise添加一个回调函数this.$router.push({name:'Cats',},()=>{})修改VueRouter原型对象上的push/replace方法在router/index.js文件中添加如下代码//获取原型对......
  • centos禁止root登录,新账户使用管理员权限
    背景:为了提供更安全可靠的外网ssh连接,计划对root用户登录做限制,停止root用户登录,使用新账号登录,可有效减小黑客入侵几率,不仅需要猜密码,还需要先猜账号,无疑大大增加入侵成本。服务器版本:centos7.6步骤一,新增用户username#useraddusername//username为想要创建的用户名#pa......
  • vue中事件修饰符.prevent.self和.self.prevent有什么区别
    v-on:click.prevent.self:会阻止所有的点击,阻止了自身的默认事件和阻止了子元素事件的向上冒泡。v-on:click.self.prevent:只会阻止对元素自身的点击,阻止了子元素事件的向上冒泡,阻止了子组件冒泡事件的默认事件。在Vue.js中,事件修饰符.prevent用于阻止事件的默认行为,.self用于阻......
  • Linux Centos 7 磁盘扩容
    背景情况在使用Centos的时候,由于上传的附件越来越多。原有的磁盘空间不足以用来存储更多的附件。也不可能通过迁移系统的方式来改善这个问题。最优解的方式就是采取扩容磁盘的方式。准备工作操作系统:Centos7(其他Linux系统类似)其他:向系统添加一块或多块磁盘开始迁移查......
  • Android 动态改变 navigation 的 startDestination, 使得已登录的用户直接跳过 LoginF
    需求:未登录用户打开App,会展示登录页面LoginFragment已登录用户打开App,直接展示MainFragmentnav_graph.xml结构如下:MainActivity.java:@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);......