A B 表的设计思路

AB表设计
以前在一家第三方结算的公司做运维DBA,在一次与开发人员探讨某个表的数据运维。那时我头脑想到AB表来切换使用,比如当A表写满后,就切到B表,那么A表就可以做运维工作。看到系统有管理,业务,日志WEB页面,我想应该有个数据运维页面,在页面上点击个按钮就改变应用程序从读A到读B的操作。当然没实现,比较在一个成型的系统不好做。去年面试个小额贷款公司,就被问到跨年问题,该表如何设计跨年。。。当时脑比较混沌没有回答好。出来后问了下朋友,朋友说采用RENAME方式。后来现在这公司,参加一次开发主导的头脑风暴,主要是评审。六张表每天都要装在数据,装完后由人工智能程序去分析,分析后写到结果表中。六张表每天都要清空再装新数据!为了不影响业务所以采用AB表方式。我当时感觉鸡冻,居然我的以前的想法现在有人去实现了。可惜接下来深度了解中后,有些遗憾!虽然采用了AB表,却采用RENAME去实现!
审核对方的SHELL脚本,基本流程是 清空表,删除索引,加载数据,创建索引,收集统计信息,把A表改名到C表,把装好数据的B表改名为A表,然后在对索引改名,最后把C表给删除。改表之前 SET LOCK_DDL_TIMEOUT=30,LOCK TABLE。。。
为了获得改名成功,设置了试图加DDL锁的等待时间,然后加表的独占锁,才开始改名。陪开发人员测试脚本,主要测试逻辑,还有注意事项,折腾了1个星期,从原来1个脚本变成了12个脚本。
本来我设想的AB表 额外加个路由表。当B表准备好了,就是数据装好了,索引重建了,信息收集完了.就去路由表更改标志位。 这样应用程序通过标志位获得当前该读取那张表。类似如下代码

SELECT TALBE_FLAG  INTO L_FLAG
FROM ROUT_TABLE
WHERE TABLE_NAME='XXX'

IF L_FLAG='A' THEN
   EXECUTE IMMEIDATE 'SELECT * FROM XXX_A';
ELSE 
   EXECUTE IMMEIDATE 'SELECT * FROM XXX_B';
END IF;

好处:
1 是不用删除C表 空间浪费
2 是不用REMANE 这样的DDL锁 带来的风险
3 不用更改索引名字

这样的脚本就比较单纯,就
1 清空装数的目标表;
2 删除索引;
3 装在数据;
4 重建索引;
5 收集统计信息;
6 更改路由表;

什么场景下使用AB表?
1 如上面的业务只读,数据由外部装入
2 跨年表 因为业务上新年一过就不处理去年的业务
3 日志写表 应用不断往一个表写入日志,该日志只是为了审计,不参与业务。日志表太大了,通过常规方式清理会影响日志写的程序。

总之那种与业务关联不强,也与其他表关联不强的表数据可以通过AB表+路由表方式进行数据维护。也可是说是数据优化!

如今互联网应用都很多了,尤其那种不可申请停机,也没有业务上停机维护时间窗口,也没有高峰和低谷时间,平时每分钟交易频繁,产生大量数据,没有下手做维护的机会。那么AB表设计就是一个不错的选项!!
关注微信公众号:https://mp.weixin.qq.com/s/xZycdqNelKzowcCnC5e73g

前篇链接 设计AB表
今天我跟朋友继续讨论AB表设计的应用场景, 从上面来说 就那么几个场景可以使用. DBA说可以用分区交换方式替代. 真的吗? A B表就这点生产空间吗?
非也 ! 因为2016年的灵感的激发,绝不是这些场景引起来的.

什么场景下使用AB表?
1 如上面的业务只读,数据由外部装入
2 跨年表 因为业务上新年一过就不处理去年的业务
3 日志写表 应用不断往一个表写入日志,该日志只是为了审计,不参与业务。日志表太大了,通过常规方式清理会影响日志写的程序。

难道不能应用在业务相关的表吗? 好像也可以哦,只有解决了读的问题,
比如说先读A表, 没数据,再去读B表. 这样就获得了数据,解决了业务数据不一致性问题. 只是要读两次!

很多7X24小时的业务系统, 互联网+的系统 基本上没有停机维护的机会.尤其是MYSQL 要给它增加字段,索引,哪怕是注解都要获取元数据锁 MDL。这样造成阻塞DML操作! 如果使用A B表就不会了,随时随刻都可以进行维护,在不处于服务状态的表进行添加个字段,添加索引,添加注解。不会阻塞写操作,读操作通过MVCC 去了。点击下切换按钮,更改路由表的 服务状态TABLE_FLAG=‘B’

SELECT TALBE_FLAG  INTO L_FLAG
FROM ROUT_TABLE
WHERE TABLE_NAME='XXX'

## DML 判断 一次DML
IF L_FLAG='A' THEN
   INSERT INTO TABLE_A VALUES('','');
ELSE 
   INSERT INTO TABLE_B VALUES('','');
END IF;

##读判断,读两次
IF L_FLAG='A' THEN 
 SELECT COUNT(1) L_EXITS FROM TABLE_A WHERE AGE=?;
  IF L_EXITS > 0 THEN
    SELECT NAME,AGE,MONEY FROM TABLE_A WHERE AGE=?;
  ELSE L_EXITS = 0 THEN
    SELECT NAME,AGE,MONEY FROM TABLE_B WHERE AGE=?;
END IF

IF L_FLAG='B' THEN 
 SELECT COUNT(1) L_EXITS FROM TABLE_B WHERE AGE=?;
  IF L_EXITS > 0 THEN
    SELECT NAME,AGE,MONEY FROM TABLE_B WHERE AGE=?;
  ELSE L_EXITS = 0 THEN
    SELECT NAME,AGE,MONEY FROM TABLE_A WHERE AGE=?;
END IF

<think>嗯,用户现在问的是关于设计思路的问题,之前已经让我介绍了如何用C++设计一个图书管理系统,现在他们可能想深入了解背后的设计理念和结构规划。我需要确保回答清晰,结构合理,并且覆盖用户可能关心的各个方面。 首先,用户之前得到了一个具体的代码示例,现在他们可能想了解为什么选择这样的结构,比如类的划分、数据结构的选用等。我需要解释每个设计决策的原因,比如为什么用类,为什么用vector来存储书籍,以及各个方法的作用。 接下来,我需要考虑用户可能的背景。他们可能有一定的编程基础,但对面向对象设计或系统架构不太熟悉。所以需要用简单明了的语言,避免过于专业的术语,同时确保解释到位。 用户的需求可能不仅仅是了解设计思路,还可能想扩展这个系统,比如添加新功能或改进现有结构。因此,在解释设计思路时,我应该提到可扩展性和模块化,这样用户知道如何进一步开发。 另外,用户之前的问题提到了主界面、存储、借还书功能,现在设计思路需要把这些部分串起来,说明各部分如何协同工作。可能需要分点讨论,比如分层设计、数据管理、用户交互等,让结构更清晰。 还要注意潜在的问题,比如异常处理、数据持久化、输入验证等,这些可能在当前代码中没有完全实现,但用户可能会关心如何改进。因此,在设计思路中应该提到这些考虑因素,以及未来可能的优化方向。 最后,确保回答符合之前的格式要求,使用中文,结构清晰,分步骤或模块说明,并且指出可能的改进点。这样用户不仅能理解当前的设计,还能知道如何进一步优化系统。</think>好的,以下是该图书管理系统的核心设计思路,分层次解析其逻辑架构和实现方法: --- ### **1. 分层设计思路** 系统采用**模块化分层设计**,分为**数据层**(书籍信息存储)、**逻辑层**(借还操作控制)和**交互层**(用户界面),确保各功能解耦。 --- ### **2. 核心模块设计** #### **(1) 数据模型层:Book类** - **目的**:抽象图书实体,定义书籍的核心属性(书名、作者等) - **关键设计**: - 使用`string`类型存储文本信息,`int`类型记录库存量 - 提供`display()`方法实现信息的统一格式化输出 - **为什么选择类?** 通过面向对象封装数据与行为,便于后续扩展(如添加ISBN编号等字段) #### **(2) 逻辑控制层:Library类** - **目的**:管理所有书籍,处理借还逻辑 - **关键设计**: ```cpp class Library { private: vector<Book> books; // 使用动态数组存储书籍集合 public: // 核心方法:增删改查 + 借还操作 }; ``` - **数据结构选择**:`vector<Book>` 动态数组便于快速遍历和随机访问,适合中小规模数据 - **去重逻辑**:`addBook()`时检查书名、作者、出版社是否完全一致 → 若存在则累加库存,否则新增记录 - **借还操作**:通过书名直接匹配库存增减,简化实现 #### **(3) 用户交互层:主界面** - **设计目标**:提供清晰的命令行菜单 - **实现逻辑**: ```cpp while(true) { // 显示菜单选项 switch(用户输入) { case '1': 添加书籍; break; case '2': 借书; break; ... } } ``` - **循环菜单**:通过`while(true)`保持系统持续运行 - **输入处理**:使用`cin`获取简单输入,适合快速原型开发 --- ### **3. 关键设计考量** #### **(1) 库存管理策略** - **借书限制**:`borrowBook()`检查`quantity > 0`防止负数库存 - **简化匹配**:当前仅通过书名匹配(实际场景需结合ISBN等唯一标识) #### **(2) 扩展性设计** - **预留接口**:如`listAll()`使用`for_each`遍历,便于替换为文件操作或数据库查询 - **可扩展字段**:Book类可轻松添加`ISBN`、`category`等属性 #### **(3) 异常处理(当前缺失)** - **待优化点**: - 输入非法字符时的处理(如输入字母时要求输入数字) - 借书时库存不足的明确提示 - 归还不存在书籍的容错 --- ### **4. 典型改进方向** ```mermaid graph LR A[当前系统] --> B[数据持久化: 文件/数据库] A --> C[精确搜索: 多条件查询] A --> D[用户系统: 记录借阅人] A --> E[日志系统: 操作记录] A --> F[GUI界面: Qt/ImGui] ``` --- ### **5. 设计模式应用建议** - **工厂模式**:若需支持多种书籍类型(如纸质书、电子书) - **单例模式**:确保全局只有一个`Library`实例 - **观察者模式**:实现库存变化时自动通知管理员 这种设计在保证基础功能的同时,为后续扩展保留了充足空间,适合作为教学示例或二次开发的起点。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值