版本控制的设计是数据库内设计的一种常见设计方案,使用时,首先,要对数据库中的表新增一条版本号字段。
版本字段内数据的设计,一般采用两种方式,一种是使用一条自增的数据,每新增一条数据, 版本号就会加一;另一种是使用生效时间和失效时间,生效时间是本条数据的创建时间,失效时间设置成一个无限远的时间,常设置成“ 9999/12/31 23:59:59”,进行区间限定。
设置版本号的作用主要有两个,一个是可以保留历史数据,另一个就是可以有效的解决并发编辑操作。如:A和B两个人同时对一条数据进行修改,两者拿到的数据都是版本1,A先修改数据完成,进行提交,在提交数据前,会先查看了下数据当前版本为1,自己则在此基础上,更替为2,修改成功。接着,B也修改数据完成,在提交数据前,也会进行一次查询,查看了下当前数据版本为2,与自己拿到的数据不符,所以B修改数据失败。只有B重新刷新,获取到新的版本2的数据后,才可以进行修改。这对于并发编辑修改数据时间过长的操作,是非常有必要的。
上面的增加自增版本号方法和设置生效失效时间区间方案,虽然都能有效解决历史记录和并发修改问题,但是,每次在修改数据时,数据的主键都会变动新增,主键的变动使得关联的对象完全变动,所以需要使用一个标识,从而明确变动前后的数据是同一个对象。所以我们引入一个新的字段,即业务主键。
数据库内的主键,就是数据库内一行数据的唯一标识。而主键有分为两种:
(1)业务主键:采用业务数据中的某个唯一字段作为主键,如:公司内部的员工号,车辆管理的车牌号,人员档案的身份证号。业务主键即使独立开来,也仍然具有意义。但是这种主键会有比较大的变动可能性,如数据升级、人员调动等,将给数据的维护带来较大困难,并且,并不能真正意义上保证主键唯一性,如当前身份证由于各种原因,还是有极小概率的重复。所以常不建议直接使用其作为数据主键。
(2)逻辑主键:不采用任何数据作为主键,而是采用一个没有意义的数值作为主键。常见的两种方式为主键自增和UUID随机生成主键,主键自增的优势在于生成主键的速度较快,大约比UUID快30倍左右,但主键自增会面临合表时的主键冲突问题,这个是UUID的优势。
则在逻辑主键基础上,引入业务主键,其使用情形如下:
(逻辑)主键id | 用户名 | 年龄 | 员工号(业务主键id) | 版本号 |
---|---|---|---|---|
1 | jack | 16 | 1 | 1 |
2 | jack | 17 | 1 | 2 |
上表中,jack的员工号为1,这是其业务主键,修改前后,该数据是不会发生变化的,原数据为第一条,修改后新增第二条,虽然逻辑主键自增了,但是可以通过员工号(业务主键)确定该数据的唯一归属对象。
而对于获取数据库表中的最新版本的数据,可以采用如下sql语句进行获取:
select 要查询的字段名 from 表名 as a where 版本号字段 = (select max(b.版本号字段) from 表名 as b where a.业务主键id = b.业务主键id);
如user数据表:
select * from user as a where vb=(select max(b.vb) from user as b where a.number = b.number);
这样就可以获得全部都是最新版本的数据表。
还需要说明的一点是,例如本例的情况下,如果有关联本表的其他表,利用业务主键id,作为其他表的外键,可以在只修改本表时,不影响其他表的数据。