Home  >  Article  >  Database  >  企业级开发中关系型数据库做接口传输的设计思考

企业级开发中关系型数据库做接口传输的设计思考

WBOY
WBOYOriginal
2016-06-07 15:28:211385browse

企业级开发中关系型数据库做接口传输的设计思考 所谓思考,就是思考。 本文以oracle数据库为例,探讨一下企业级开发中,用数据库做中间表传输数据的一些设计思考。欢迎留言补充指正。 1、 接口双方,谁来主宰定义权 一般的原则是,接收方负责定义接口数据格

企业级开发中关系型数据库做接口传输的设计思考

所谓思考,就是思考。

本文以oracle数据库为例,探讨一下企业级开发中,用数据库做中间表传输数据的一些设计思考。欢迎留言补充指正。

1、 接口双方,谁来主宰定义权

一般的原则是,接收方负责定义接口数据格式和规则。因为接收方必须非常清楚自己要接收什么数据,如果这点都不知道,那可以不用做了。其次,还涉及到数据转换问题,由发送方将某些接收方无法识别的档案数据,转换成接收方能识别的档案数据,再发送给接收方,会比较合理。因为这样在接口交互中,交互的数据,就是一个完整的可接收数据,而不是一个半成品数据。

但也有2种特殊的情况,第1种特殊情况是遵循了兵法原则,先下手为强。尤其出现在后进场的项目组,虽然处于数据接收方的角色,但因为提前进场的项目组已经将发送接口定义好也开发完成了,所以为了避免重复劳动,接收方只能将就发送方的定义规则。

第2种特殊情况是,接收方是一个基础数据上比较完整的系统,而发送方是一个小系统,基础数据比较单一。这就是基础数据转换问题导致的控制权反转。

有些公司的基础数据比较混乱,举个极端例子:A系统定义一套人员编码,全部以字母A开头。B系统定义一套人员编码,全部以字母B开头…以此类推。每一个系统中的人员编码,实际上都是有1-1对应关系的,只是,这种对应关系,仅仅维护在主要系统A中。此时,A系统和B系统做人员接口,要求B系统传输人员数据。若此时由接收方负责定义接口,则A系统会希望B系统把人员编码转换成A系统的格式,再发送给A。但是B系统却无法做到档案的转换,所以只能按照B系统的原则来定义接口。

正如上例,有时会因为种种压力而要求B系统中维护一套对应规则,再由B系统负责接口编码转换。实质上,编码转换的工作量不大,但维护一套对应规则就比较麻烦而且是长期的工作量。如果这套规则对B系统从业务上毫无必要的话,那B系统要非常坚决的反对这种不正当要求。

2、 流水号和编码,谁才是真正的主键

企业级数据中,几乎所有档案都有编码,比如人员编码,公司编码,部门编码。。。这些编码都有一个特点,即不重复。应该不会有2个员工,共用一个人员编码的情况吧。如果现在有一个任务,是通过db来从对方系统传输人员数据,那是否可以用人员编码来作为中间表的主键呢?

当然是不行的。考虑一个最简单的情况,如果人员编码A,发送一次中间表;然后A离职,另一个人入职,启用了原有的编码A,则此时,需要将人员编码A(其实是另一个人)再次发送中间表,那会破坏主键唯一性原则。

现在来想想2个概念,我称它为系统级主键和业务级主键,所谓业务级主键,可以理解成人员编码这种,可以在软件前台界面中看到的主键,它的特点是用户可编辑并且唯一。其生命周期与业务相关,比如人员A离职后,业务级主键A消失;下一个人入职启用了编码A,则业务级主键A神奇复活。

系统级主键,可以理解成流水号,不可以在软件前台界面中看到,不可被用户编辑,由系统底层通过规则创建,此规则与业务逻辑毫无关系。生命周期与此条数据在数据库中的生命是一致的,简单讲,只有delete才会删除此主键,并且没有人工干预的话,是不会神奇复活的。

说到流水号,还有一个比较相近的是批次号。主要出现在db模式接口中,需要对多笔数据执行一个数据库事务操作时。批次号有系统级主键的部分特点,也有业务级主键的部分特点(比如有时是前台可见的)。

3、 越来越通用的不是功能,而是表?

经常有见到将多个种类的需要传输的数据,通过各种潜规则而保存到一个数据库中间表的情况。或者是把原本需要通过主子表、或者关系表的数据,整合到一个表或一个字段中,用各种潜规则来分开标记,赤裸裸的违背了“关系型”数据库原则。

做接口设计的时候,若是能把功能设计的更具通用,从而使接口表数量越少,则越是高端大气上档次。所以datatype字段被大量的使用,自定义项def被青睐。若是一个数据库中间表在定义的时候,不留出十几个自定义项,就感觉很快要出事似的。

笔者有2个观点,第1,给数据库增加字段,非常非常非常的简单。若是用自定义项,还要增加维护一个自定义项具体业务功能说明,反而麻烦。第2,把多种数据放到一个表中用datatype区分,非常非常非常的复杂。造成某些字段含义不单一,数据冗余度高,数据库索引无法彻底分析字段内容的规则,效率下降。

具体需要做几个接口,是业务需求决定的,不是建几张数据库表决定的。少建表,对开发代码工作量没有任何的节约,反而增加工作量。例如:字段A,在数据类型1中是必输,但数据类型2中是不输入。则将2种数据类型混合到一张表的话,接收数据时,就要程序校验字段的必输性。若是分开2张数据库表,则数据类型1的字段A,可以设置数据库约束必输,程序无需校验。而数据类型2的字段A,根本就不用定义此字段了。

4、 对丢失数据的恐惧!

接口系统上线后,若是丢了一条数据,容易造成发送方和接收方互相推卸责任,并且没有很好的方式找到证据。于是备份中间表的数据成为习惯,或者一不小心将备份表作为接口传输的一个流程环节,直接设计成了状态同步表。

先说备份表,千万不要把备份表做成同步表。说的直接一点,在写备份表的程序中,只允许执行insert,不允许任何的select update delete。这样才像备份表。想想日志文件,不都是write吗?不会有程序去read edit delete日志文件吧。

如果你在写备份表程序的时候,非常不小心的使用了select update delete,那么你就把备份表做成了状态同步表了,也就是说,此表中的数据的状态,与整个接口程序和最终数据的状态、与后续程序流程都有了耦合。千万不要这么做。

如何避免数据丢失纠纷,下面是笔者提供的一种方案:

首先是参与接口工程的角色,有发送方、接收方、客户方(第三方)。客户方提出需求,接收方定义中间表,发送方配合。例如中间表t

流水号字段

数据字段

状态字段

id

Data

status

 

 

 

1、 将数据库中间表t,新建在客户方数据库中,既不是发送方数据库,也不是接收方数据库。

2、 在客户方数据库中,新建用户user_send,并将中间表t的查询和插入权限赋予此用户。Grant select,insert on t to user_send。将user_send用户提供给发送方,这样发送方只能查询和写入数据到中间表 ,无法删除数据或更改数据。

3、 在客户方数据库中,新建用户user_receive,并将中间表t的查询和状态字段的更新权限赋予此用户。Grant select,update(status) on t to user_receive。将user_ receive用户提供给接收方,这样接收方只能查询数据,并且只能修改status状态字段,不能修改其它字段,也不能插入和删除数据。

根据上述方案,通过数据库的权限配置,已经将发送方和接收方的责任权限彻底分开,也不必担心数据丢失或被篡改。

5、 对空值的偏爱

数据库的空值是非常特殊的一种类型,并且对于空值如何处理,关系型数据库没有做统一的规定,SQL语言也没有做统一的规定。这是一个非常危险的消息,因为空值可能一不小心造成bug。

例如oracle的varchar2类型字段,select *from table where column = ‘’这种查询是无效的,应该写成select*from table where column is null。换一个数据库,写法又不一样了。

所以在做数据库接口设计的时候,尽量保证字段是有值的。

我经常看到这样的设计,字段A,传值1表示***,传值2表示xxx,若传空值,表示$$$。这是糟糕的设计。

即使SQL和关系型数据库对空值做了统一规范,也不应该在中间表字段中定义空值,这样相当于把一个空值赋予业务含义。并且,可以有空值的字段,不能配置数据库非空约束。还可能由于发送方程序bug而导致没有给字段写值却成了合法的输入。

6、 ABCD还是1234

定义什么样的状态值往往困扰我们。我们已经受够了太多的状态字段和状态值。有的状态字段值分别是ABCD…有的值分别是1234…时间长了,我们已经无法清楚的记住哪个字段是哪个含义,哪个值是哪个含义

真的有必要那么多的状态吗?仔细想想应该没有,除了常见的“初始init”“成功success”“失败fail”“异常error”,我想不出哪个状态是没有办法用英文单词来明确区分的。所以为什么不查查字典,用简单明了的英文单词来描述状态值呢,这样一看就懂了。

7、 唯恐天下不乱的不是记者而是智者

不出问题永远不知道错在哪,如果你懂了,不要说出去,等出了问题,再说出来

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn