请教大佬一个问题,有一个需求更新 30 张表的一个字段,怎么去实现?

2022-10-11 15:53:14 +08:00
 longmeier90
我们公司业务场景是 把两个患者合并成一个患者,但是就需要把库里的 30 张表(未来会更多表...都是加的冗余字段)的信息更新一下。
那么线上系统发起一个需求,怎么能在不影响性能,而且还有保证信息的完整性的情况下去实现。

1. 如果保证完整性就需要加事务,但是就会锁表造成系统卡顿,app 转圈(之前的一些其他业务事务出现类似的)影响线上业务。
2. 不加事务,怎么能保证数据的一致性。

3.向这种场景应该是常见的吧,大佬都是怎么设计的?

3657 次点击
所在节点    Python
43 条回复
lmshl
2022-10-11 17:10:39 +08:00
写入的时候保持相同的顺序去锁,SELECT FOR UPDATE
liaohongxing
2022-10-11 17:14:57 +08:00
innodb 和事务已用多年。都是行级锁 。哪里需要锁表
cubecube
2022-10-11 17:15:46 +08:00
@westoy 现在的开发模式,不得不冗余分割,因为人员有流动,项目也不一定能连续的持续下去
timethinker
2022-10-11 17:16:24 +08:00
问题不在于有哪些解决办法,而在你能承受什么样的成本。
你是想在屎山上继续堆屎还是来个大扫除为将来留下更多的操作空间?

现状就是你有几十张表需要去更新,在不考虑重构的前提下,你能选择的方案并不多:
1 、你想要在一个事务里面进行更新,这也是最简单的办法,但是你会担心说影响性能。
2 、一张表一张表的更新你又会担心无法保证数据的完整性。

如果是我的话,在没有重构的选择情况下,在没有了解业务领域的情况下,我会选 1 ,这也意味着我不会考虑系统的性能,也不会考虑到系统的可用性问题。

如果你是系统的设计人员,如果你有权决定是否应该重构,那么就应该考虑到这些问题(可用性以及可靠性)如何影响业务系统的架构设计,这些问题你应该最了解,如果你还不了解,那么要先去了解,因为只有你先了解以后,你才能够根据规模来决定应该如何重构,重构哪些方面可以解决关键的问题,以及重构的成本是否可以承受。
IvanLi127
2022-10-11 17:19:28 +08:00
我觉得大佬会选择重写整个系统,30 张表都冗余一次这个字段,那这个字段它是不是应该住缓存里?
如果没有这个冗余字段,性能会很差么?冗余字段要么写扩散,要么放弃实时性,只保证最终一致性。
pengtdyd
2022-10-11 17:20:03 +08:00
一个需求更新 30 张表。。。。。。。。技术 leader 到底什么水平啊。
liaohongxing
2022-10-11 17:22:52 +08:00
现在还不用事务,不知道你们多表更新的代码是怎么写的哈。要是一个转账场景 ,一个扣款 ,一个入款 。要是意外中途断掉了,入款岂不是平白无故丢了一笔钱。想想就很可怕。
longmeier90
2022-10-11 17:23:21 +08:00
@pengtdyd 单独讨论技术方案,不扯其他
leeg810312
2022-10-11 18:46:21 +08:00
不加事务,不可能保证一致。如果行锁仍然会影响业务,那么有 2 个选项,一个是用 2 个数据库做读写分离,另一个是读请求都是读缓存,写改成异步,事务写完再更新缓存。
someonedeng
2022-10-11 18:59:22 +08:00
能不能惰性处理,比如涉及到了这个患者的查询 /更新 就处理下这个患者就行了
xy90321
2022-10-11 19:18:46 +08:00
建一张用户更新的临时表,PK 是 操作 ID ➕ 要更新的表名

每次要合并时候生成个唯一的操作 ID ,然后往临时表里用这个 ID 为每张要更新的表插一条记录,按照你目前的表设计是每次合并需要插 30 条

剩下的就是更新程序确保按照一定的顺序一条条处理临时表里的数据就可以了,人肉事务保证最终结果一致性(但不保证过程一致性和实时性,也就是更新过程中会有 20 张更新了,10 张还没更新,一部分界面表示不一致)

说白了,就是有序 MQ 的思路,但是看你们这系统的样子也不像有 MQ ,就自己来吧
route
2022-10-11 19:42:28 +08:00
1. 先将数据同步到某个中间件,如 kafka ,只做访问不能修改,原始数据记为 db1
2. 在某个时间点确定同步完成后,新建一模一样的表,新来的存储信息都往这个表存储,记为 db2
3. 新建一个数据库,以后使用这个数据库做生产,记为 db3
4. 线下完成好 db1 合并数据再导入 db3
5. 线下完成好 db2 合并数据再导入 db3
Maxwe11
2022-10-11 19:47:22 +08:00
首先,一定不能这样无休止为了“方便”在无数个表上加字段;

看样子系统也不太可能短期内重构;

但这样无休止加下去早晚会出问题,所以为了稳定,短期内无法做大调整的时候,我们以往的经验是先做分层;

把你现在手里的表都拿出来,先做一次分析,哪些是业务核心表,哪些是报表数据等等,把表类型先分层,然后建层,就像建数据分析集市,哪些是事实哪些是维度哪些是业务层哪些是汇聚层等等,保持业务系统不变,但是把逻辑通过数据处理层解决,这样就可以把 1 对无限多的问题转换成局部问题。
buster
2022-10-11 20:04:11 +08:00
异步处理嘛,执行速度不能保证,业务上应该不允许
同步嘛,又会有慢和锁的问题

1. 最理想状态,应该放弃全部更新的这个念头
2. 实际干活,我觉得应该跟业务方沟通是否有妥协可能性,比如放弃一定的响应时间,把执行都搬到异步那边去做,等异步完成之后才可以看到最新的状态,否则就是 updating ,这样就只是多了额外的合并功能的业务代码,不影响原有逻辑,异步程序,30 次的大事务拆成小事务,维护一个 log 表来记录。
NewYear
2022-10-12 09:30:30 +08:00
更新关键表,后台跑一个线程去更新冗余表吧。
zmal
2022-10-12 10:30:29 +08:00
异步的方案上面的回复都给出了,大差不差就那些东西。
异步的问题无非是数据更新有延迟或不同步。理论上业务肯定有优先级,不必做到 30 多张表全部实时。如果还是有疑虑或者业务方要求必须实时,可以在异步的方案上加一张 patch 表,配合异步方案对这些表的查询结果用一个拦截器做实时补偿。
JohnBull
2022-10-12 13:55:19 +08:00
医务系统应该不是 7x24,花一个月时间每天下班后用事务无脑跑批可以的吧
wxf666
2022-10-12 14:37:35 +08:00
@longmeier90

> 加一些冗余字段是为了查询是方便。很多统计都会联表查询数据量大的时候就会慢

好奇问一下,一般会连多少张表?被连的表一般有多大?(比如,一般连 千万级患者表 等类似级别的 5 张表?)
longmeier90
2022-10-12 15:38:59 +08:00
@wxf666 不等,其他同事写的 SQL 都不好控制,再加上前期都是用外键关联查,有的 7 、8 个 left join ,随着业务数据增加有的大表 100 万数量级。
wxf666
2022-10-12 15:54:06 +08:00
@longmeier90 就算是 8 个 100 万行的表,每行 1KB 的数据,全部缓存也大概需要不到 8 GB 内存而已呀

是内存不够,导致联表慢吗?

如果不依赖数据库的 left join ,而是自己获取主要数据后,再手动查询 8 次表(若已花 8 GB 代价全部缓存至内存中了),最后组装数据,也很慢吗?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/886103

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX