ent M2M模型在pxc集群中的一个大坑
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集群中的一个大坑的更多相关文章
- 集群: 如何在spring 任务中 获得集群中的一个web 容器的端口号?
系统是两台机器, 跑四个 web 容器, 每台机器两个容器 . nginx+memcached+quartz集群,web容器为 tomcat . web 应用中 用到spring 跑多个任务,任务只能 ...
- 02使用java脚本向Pxc集群写入数据
使用java脚本向Pxc集群写入数据 批量写入pxc集群程序 导入mysql驱动包 # 批量插入数据的java脚本 package pxc_demo; import java.sql.Connecti ...
- docker swarm英文文档学习-8-在集群中部署服务
Deploy services to a swarm在集群中部署服务 集群服务使用声明式模型,这意味着你需要定义服务的所需状态,并依赖Docker来维护该状态.该状态包括以下信息(但不限于): 应该运 ...
- PXC集群资料整理
1.mysql集群方案对比 方案1 NDBCluster 参考:https://www.cnblogs.com/kevingrace/p/5685371.html?utm_source=itdad ...
- MySQL之PXC集群搭建
一.PXC 介绍 1.1 PXC 简介 PXC 是一套 MySQL 高可用集群解决方案,与传统的基于主从复制模式的集群架构相比 PXC 最突出特点就是解决了诟病已久的数据复制延迟问题,基本上可以达到实 ...
- 对比PXC集群与主从架构在一致性上的区别
在上一篇文章中,已经完成了三节点PXC集群的搭建,现在搭建node3的从库node4,并且有如下测试: 搭建node3的从库,代号node4 测试1: 先断开node3节点,然后在node1构造数据, ...
- MySQL数据库高可用集群搭建-PXC集群部署
Percona XtraDB Cluster(下文简称PXC集群)提供了MySQL高可用的一种实现方法.集群是有节点组成的,推荐配置至少3个节点,但是也可以运行在2个节点上. PXC原理描述: 分布式 ...
- 将自己写的windows服务加入到windows集群中
最近发现windows集群能进行很多自定义,比如在集群中加入自己编写的服务. 能自定义的可不少,截个图: 本次演示中,只想用“通用服务”这个类型. 先列下步骤 编写一个记录时间的Windows服务,这 ...
- Storm集群中执行的各种组件及其并行
一.Storm中执行的组件 我们知道,Storm的强大之处就是能够非常easy地在集群中横向拓展它的计算能力,它会把整个运算过程切割成多个独立的tasks在集群中进行并行计算.在Storm中 ...
- Docker Swarm集群中部署Traefik负载均衡器
一.创建单节点的Docker Swarm集群 docker swarm init 二.在Swarm集群中创建一个网络 docker network create --driver=overlay tr ...
随机推荐
- PHP 计算机码、位运算、运算符优先级
计算机码 计算机在实际存储数据的时候,是采用编码规则的(二进制编码) 计算机码存储的过程: 原码.反码和补码,数值最左边一位用来充当符号位:符号为正数为0,负数为1 原码:数据本身从十进制转换为二进制 ...
- DVWA-File Inclusion(文件包含)
文件包含漏洞,当我们在一个代码文件想要引入.嵌套另一个代码文件的时候,就是文件包含. 常见的文件包含函数有include require等函数. 这两个函数的区别就是include在包含文件不存在时p ...
- Linux 命令之 tar 操作符
tar -c: 建立压缩档案 -x:解压 -t:查看内容 -r:向压缩归档文件末尾追加文件 -u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个 ...
- ABAP 屏幕开发-仿采购订单
1.功能说明 本文档通过一个简单的实例,仿照采购订单的界面,介绍屏幕开发. 2.效果展示 3.功能实现 3.1界面框架 从界面上看,整个界面框架分为四部分.抬头行,抬头页签,行项目,项目细节.其中抬头 ...
- 【Visual Leak Detector】QT 中 VLD 输出解析(一)
说明 使用 VLD 内存泄漏检测工具辅助开发时整理的学习笔记. 目录 说明 1. 使用方式 2. 无内存泄漏时的输出报告 1. 使用方式 在 QT 中使用 VLD 的方法可以查看另外几篇博客: [Vi ...
- SpringBoot的EnableCaching简述
Spring Boot中的EnableCaching简述 spring boot中自带有数据缓存机制,主要通过其org.springframework.cache包下的各种类来实现. EnableCa ...
- 几个对js帮助挺多的大佬写的博客
深入理解javascript原型和闭包(完结) JavaScript系列文章 同步异步回调DEMO知乎大佬的this与new解释 宏任务与微任务解析 js闭包 Vue项目中技巧ts学习 ES6基础入门 ...
- 3d基础 - 从模型坐标到屏幕坐标
在 3D 引擎中,场景通常被描述为三维空间中的模型或对象,每个模型对象由许多三维顶点组成.最终,这些模型对象将在平面屏幕上呈现和显示. 渲染场景始终相对于摄像机,因此,还必须相对于摄像机的视图定义场景 ...
- Django后端 服务器找不到template(路径问题)
Django后端 服务器找不到template(路径问题) 该代码在本地跑没有任何问题, 但是上传到服务器上报错找不到模板或者模板不存在. 看网页最下方报错(一定要看报错!!)显示路径有问题 问题原因 ...
- ros-python学习样例笔记
1.通信基本原理介绍 待写 2.三种通信方式的程序样例(python版) 2.1 topic 通信方式(非自定义和自定义) 2.1.1 创建工作空间和topic功能包 在ubuntu中打开命令行,输入 ...