侠义的CMDB都是偏向纯资产管理,但运维系统每每围绕着这些资产中心,从资产进行不断外充扩容数据库
在其基础以外扩展出各功能,经过cmdb 扩展出各个子系统 运维
涉及工具: workbenchide
一个例子:设计一个数据库实现主机信息、交换机信息,如何将之间的信息关联起来
工具
初步的传统设计:spa
主机 |
交换机 |
user |
资产编号 |
资产编号 |
部门 |
硬件配置信息 |
IDC |
使用人设计 |
机柜位置 |
机柜位置 |
业务线 |
外连ip |
外网IP |
|
业务线 |
内网IP |
|
备注 |
业务线 |
|
备注 |
每种属性都是不一样的,就算名称同样,那么字段大小是否考虑过?orm
到底多少个字段合适,拆表的方式的话,须要拆多少张表?blog
传统设计来说,确定是一个资产一个表,那么关系型数据库多少张合适?ip
若是真是这样的状况,才能引出CMDBrem
能够认为不一样型号的产品都是一个资产,那么不一样产品放在一张表中确定不现实
每一个场景一张表,那么若是新加场景如何考虑?增长字段?增长多少字段?
因此咱们要引入一种方式进行实现这些信息,不一样信息是不同的,好比id信息是一种信息,主机名等也是一种信息,即便分析的再好,一旦普遍使用起来,那么需求也陆续膨胀
这样的设计带来很大的问题:字段没法控制,扩展性不够,大量的字段冗余,看似名字差很少,名字也差很少
引入CMDB
初期版本设计太繁琐,须要用到的表关联无计其数,因此须要引入一种新的设计方式来进行,经过字段表进行关联开
虚拟表设计
先创建两个表,Schema 和Filed 表
Schema 用于存放全部表
Filed 用于存放各类表的字段,这样大多数的字段均可以撑得住
设计Schema
这里存放着表信息,可是不存放字段
那么这里的意思确定是一行对应一个表,至关于Schema 一个id对应一个表
不要看字段,只看行
好比主机表:id=1 name=host desc="描述主机信息"
好比交换机:id=2 name=sw desc="描述交换机信息"
那么它的具体字段是存放在Filed表
设计Filed表
# meta是元数据
从关联的表,逐渐以每一行来表述,每一行都表明一个字段
首先考虑是一对多仍是多对多
要求一个字段只能对应某一个明确的表中,即便字段名称同样,可是类型不同,类型即便同样其余属性也不同,即便同一个字段,可是所谓的描述信息不同,有的int 有的bigint 等等
即便看似像同一字段,可复用的功能性不是很强,可是实现可复用状况必定很高
因此采起简单化的设计:经过不一样表的字段和其余表的字段没有任何关系
为了简化这样的关系,这里的meta描述是不同的
那么这两个表如何创建关联?
一个filed id只能属于一张表,好比只能属于host表
多对一关系的创建
再来看一下filed表结构,它不但帮咱们建了字段还添加了主键
查看外键约束
明确说明了外键是引用了schema 这个表,
并且用的是本身的id 来引用的schema id
理解这样的关系
假设:
schema
id =1
name = host
meta = 信息为主机
filed
id = 1
name = ip
meta = 先无论
schema_id BIGINT = 1
再写一个信息
id = 2
name =hostname
meta = 先无论
schema_id BIGINT =1
只要schema_id 是 1的 表明生成了一张host表
而这个host表有两个字段 1 和 2
1是描述这个ip的 2 是描述ip的
这就创建了一种关联关系
创建sw表
若是顺序日后排,那么schema id 就是2
若是序号若是对应的话,就是3 和 4,惟一表明一个字段
这种逻辑上的关系被称为虚拟表
再有一个资产来的话,再加一张表就能够了,无非就是加了一行
以上是一对多关系,在多端添加字段schema_id 解决
描述资产比较难,不一样资产有不一样的属性,比较难在一张表中设计固定个数
因此经过schema 和 filed 组合 在filed表中创建多个记录来描述,只要在filed表中增长一条记录描述便可
这样二者构建成了一个虚拟表,来描述逻辑上的表
schema 只描述表是谁
filed 只描述字段,动态添加
中间经过外键约束来构建成虚拟表,达到动态增长资产的需求
一个栗子
需求
创建一个业务 ipaddress表,对应schema_id 为 10,它有2个字段,字段的描述在filed中,
filed.id = 1, name 和字段 filed.id = 5,name 这两部分构成一张表的定义
分析
一个字段是一行记录在filed表中,能够跟其造成一张逻辑表,就是ipaddres表
ipaddress表对应的schema_id 为10
必须定义两个ipaddress,id确定不同的,可是描述不同,这样确定搞混,建议再加一个UQ 保证名字不重复
还须要根据提交的逻辑表名称,万一尾部多敲空格,那么是否须要检验空格
逻辑表设计
加入一个表entity,用于记录主机,一对多关系,一个主机的描述信息只属于一个
设计字段
id | BIGINT | 惟一标识虚拟表的记录 |
key | VARCHAR | 用于存放UUID |
添加value表
id | BIGINT | 自增 |
value | VARCHAR | 存什么? |
如今的咱们想的是将这些信息存放于value表中
这样就引出了两个字段:IP和HOSTNAME
那么回到entity中,既然是存值,那么是必须有id 惟一标识,新加字段
entity 与 value关联关系:
一对多关系,entity只有一个id,value中有多个字段,那么为了描述这一个id对应的一行记录,这两个字段都要放在value中
如何描述字段,如何知道是哪一个字段?那么filed还须要与value创建关系
创建表关系
记录哪一个虚拟表彻底靠schema_id 来表示,好比schema_id = 1 那么就至关于找host表
假如描述这边的字段该如何去关联?
描述字段关系
这里value 对应的就是就是entity_id 的而entity 又是惟一对应了schema_id
虽然是多端,这样看只能对应一个,可是关联起来以后从schema表中就可以充分体现出是对应多个表id
只不过是中间作了一层过分,这样每一个表只对应一个id便可。 可是不能描述对应的哪些字段,所需还须要与filed进行关联
这样后期加字段或者表的时候直接加一行记录便可
若是在使用的一张表在使用中,添加字段的话,物理结构也跟随发生改变,那若是是虚拟表在filed表中添加字段,那么就又生成了filed表的id来对应一些信息
那这样的话添加的代价会降低不少,假如字段描述为空的话原来的虚拟表生成的记录能够不动,若是不为空能够作一系列缺省值的设置
由filed表中的meta中进行定义字段 多类型
能够有约束也能够没有 代码中写明确便可,看实际场景,设计的时候先设计主表,将最关联的几张表列出,这几个表中又有其余描述性的信息在其余表里依次作join就能够了,其余信息再进行关联
生成工程
-- MySQL Workbench Forward Engineering SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0; SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0; SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES'; -- ----------------------------------------------------- -- Schema cmdb -- ----------------------------------------------------- -- ----------------------------------------------------- -- Schema cmdb -- ----------------------------------------------------- CREATE SCHEMA IF NOT EXISTS `cmdb` DEFAULT CHARACTER SET utf8 ; USE `cmdb` ; -- ----------------------------------------------------- -- Table `cmdb`.`schema` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `cmdb`.`schema` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `name` VARCHAR(45) NOT NULL, `desc` VARCHAR(45) NULL, PRIMARY KEY (`id`)) ENGINE = InnoDB; -- ----------------------------------------------------- -- Table `cmdb`.`field` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `cmdb`.`field` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `name` VARCHAR(45) NOT NULL, `meta` TEXT NULL, `schema_id` BIGINT NOT NULL, PRIMARY KEY (`id`), INDEX `fk_field_schema_idx` (`schema_id` ASC), CONSTRAINT `fk_field_schema` FOREIGN KEY (`schema_id`) REFERENCES `cmdb`.`schema` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB; -- ----------------------------------------------------- -- Table `cmdb`.`entity` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `cmdb`.`entity` ( `id` INT NOT NULL, `key` VARCHAR(45) NOT NULL COMMENT '惟一描述', `schema_id` BIGINT NOT NULL, PRIMARY KEY (`id`), INDEX `fk_entity_schema1_idx` (`schema_id` ASC), CONSTRAINT `fk_entity_schema1` FOREIGN KEY (`schema_id`) REFERENCES `cmdb`.`schema` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB; -- ----------------------------------------------------- -- Table `cmdb`.`value` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `cmdb`.`value` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `value` VARCHAR(45) NOT NULL, `field_id` BIGINT NOT NULL, `entity_id` INT NOT NULL, PRIMARY KEY (`id`), INDEX `fk_value_field1_idx` (`field_id` ASC), INDEX `fk_value_entity1_idx` (`entity_id` ASC), CONSTRAINT `fk_value_field1` FOREIGN KEY (`field_id`) REFERENCES `cmdb`.`field` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT `fk_value_entity1` FOREIGN KEY (`entity_id`) REFERENCES `cmdb`.`entity` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB COMMENT = ''; SET SQL_MODE=@OLD_SQL_MODE; SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS; SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;