作者:李瑜宁
起源:https://juejin.cn/post/684490…
笔者的动静字段扩大解决方案次要针对 Mysql 5.7.8 以下版本,在 Mysql 5.7.8 曾经新增 JSON Data Type,同样实用该计划,而且状况变得更加简略。
痛点
软件行业惟一不变的就是变动,比方性能上线之后,客户或 PM 须要对已有的性能减少一些正当的需要,实现这些工作必须通过增加字段解决,或者某些性能的实现须要通过减少字段来升高实现的复杂性等等。
这些问题都会改变线上的数据库表构造,一旦改变就会导致锁表,会使所有的写入操作始终期待,直到表锁敞开,特地是对于数据量大的热点表,增加一个字段可能会因为锁表工夫过长而导致局部申请超时,这可能会 对企业间接造成经济上的损失。
解决方案
减少 json 格局的扩大字段。
上面配合一些代码来形容这个解决方案,读者便于去了解。
mysql 数据库脚本:
DROP TABLE IF EXISTS `cs_dustbin`;
CREATE TABLE IF NOT EXISTS `cs_dustbin` (`id` VARCHAR(45) NOT NULL COMMENT '主键自增 id',
`rfid_no` VARCHAR(20) NOT NULL COMMENT 'rfid 卡号',
`state` INT(1) NOT NULL COMMENT '垃圾桶状态:0:已登记;1:未应用;2:待应用;3:已应用(绑定收集点);',
`user_id` INT NOT NULL COMMENT '注销人,负责录入垃圾桶的人',
`type` INT(1) NOT NULL DEFAULT 1 COMMENT '垃圾桶类型:1:餐厨垃圾桶',
`street_code` INT(11) DEFAULT NULL COMMENT '所在镇街 code,依据状态,这里的含意可能是领用镇街、退还镇街。',
`create_time` DATETIME NOT NULL DEFAULT now() COMMENT '创立工夫',
`update_time` DATETIME NOT NULL DEFAULT now() COMMENT '更新工夫',
`ext` VARCHAR(1000) NOT NULL DEFAULT '{}' COMMENT '扩大字段',
...
PRIMARY KEY (`id`))
ENGINE = InnoDB
COMMENT = '垃圾桶表';
Java 代码:
import com.alibaba.fastjson.JSON;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.List;
/**
* 垃圾桶实体
* Created by Blink on 6/28/2018 AD.
*
* @author Blink
*/
@Data
public class Dustbin {
private String id;
/**
* rfid 卡号
*/
@NotNull
private String rfidNo;
/**
* 垃圾桶状态:0:已登记;1:未应用;2:待应用;3:已应用(绑定收集点);* 对应 Dustbin.StateEnum 类
*/
@NotNull
private Integer state;
/**
* 录入垃圾桶的人员 id
*/
@NotNull
private Long userId;
/**
* 垃圾桶类型:1:餐厨垃圾桶
* DefaultValue: 1
*/
@NotNull
private Integer type;
/**
* 所在镇街 code
* 依据状态,这里的含意可能是领用镇街、退还镇街
*/
private Integer streetCode;
/**
* 创立工夫
* defaultValue : now()
*/
@NotNull
private Date createTime;
/**
* 更新工夫
*/
@NotNull
private Date updateTime;
/**
* 扩大字段,具体数据查看 DustbinExt.java
* DefaultValue: {}
*/
private String ext;
...
public DustbinExt getExtObject() {return JSON.parseObject(this.getExt(), DustbinExt.class);
}
public void setExtObject(DustbinExt ext) {this.ext = JSON.toJSONString(ext);
}
/**
* 垃圾桶扩大属性
* Created by Blink on 6/28/2018 AD.
*
* @author Blink
*/
@Data
public static class DustbinExt {
/**
* 所在镇街
* 依据状态,这里的含意可能是领用镇街、退还镇街、绑定的镇街
*/
private String street;
/**
* 客户(收集点)id,绑定收集点的时候须要填入
* 依据目前的需要(2018-06-29),当收集点解绑的时候
* 须要保留垃圾桶最新绑定收集点名称,所以在解绑垃圾桶的时候不会把这个信息删掉
* 只有当绑定收集点的时候才把他笼罩
*/
private Long customerId;
/**
* 客户(收集点)名称,绑定收集点的时候须要填入
* 依据目前的需要(2018-06-29),当收集点解绑的时候
* 须要保留垃圾桶最新绑定收集点名称,所以在解绑垃圾桶的时候不会把这个信息删掉
* 只有当绑定收集点的时候才把他笼罩
*/
private String customer;
/**
* 损坏部位
* 1:桶盖;2:桶口;3:桶身;4:桶轴;5:桶底;6:桶轮;* 对应 DustbinDamagePartEnum 类
*/
private List<Integer> parts;
}
...
}
mysql 脚本能够看到扩大字段的信息:
ext VARCHAR(1000) NOT NULL DEFAULT '{}' COMMENT '扩大字段'
能够看到这么一段 Java 代码:
...
/**
* 扩大字段,具体字段查看 DustbinExt 类
* DefaultValue: {}
*/
private String ext;
public DustbinExt getExtObject() {return JSON.parseObject(this.getExt(), DustbinExt.class);
}
public void setExtObject(DustbinExt ext) {this.ext = JSON.toJSONString(ext);
}
...
能够看到 ext
字段就是用来存储 json 格局的数据,它能够动静地减少任何字段,甚至是对象,不须要通过 DDL(Data Definition Language)去创立字段,非常适合用来解决下面提到的问题。
Java 代码在这里起到辅助性作用,通过定义一个外部类来治理扩大字段的属性,不便咱们理解和治理扩大字段,进步代码的可读性和可维护性,java 这种形式也是笔者总结进去的较为优雅的做法(个人观点)。
局限性
有教训的读者可能会提出,ext
字段在 Mysql 5.7.8 以下版本无奈对扩大字段中的某一个或一部分字段建设索引,因为 Mysql 5.7.8 版本以下不反对(Mysql 5.7.8 反对为 Json Data Type 建设索引)。
没错,这是这个解决方案的一个局限性,在 Mysql 5.7.8 以下版本,我的倡议是,ext 扩大字段不要存储热点数据,只存储非热点数据,这样就能够防止查问操作,升高保护 ext
字段带来的老本和危险,那如何辨认新增字段是不是热点数据呢?这个须要结合实际业务需要来判断,也能够询问对业务和技术更有教训的共事,便于读者更快得出结论。
终极版解决方案
在一些极其的状况下,变动可能来得太快,而咱们要的是缩小变动带来的老本和危险,所以在表设计之初能够依据本身教训,或者找更有教训的人寻求帮忙,预估一下须要预留多少个备用字段,再配合扩大字段,基本上能够把扭转(增加字段)表构造的次数降至一个非常少的次数。
总结
在非凡状况下,通过扩大字段 + 预留字段基本上能够做到动静扩大字段,又不会影响为热点数据建设索引的状况,这样咱们失去了一个非常灵活的表构造,便于咱们应答将来的变动,然而请留神,要保护好咱们的实体,包含外面的每一个字段,敬畏每一行代码。
近期热文举荐:
1.1,000+ 道 Java 面试题及答案整顿(2021 最新版)
2. 终于靠开源我的项目弄到 IntelliJ IDEA 激活码了,真香!
3. 阿里 Mock 工具正式开源,干掉市面上所有 Mock 工具!
4.Spring Cloud 2020.0.0 正式公布,全新颠覆性版本!
5.《Java 开发手册(嵩山版)》最新公布,速速下载!
感觉不错,别忘了顺手点赞 + 转发哦!