目 录
1. 时态概念简述
1.1 用户定义时间
1.2 有效时间
1.3 事务时间
1.4 时态数据库
2. SQL:2011 时态标准
2.1 有效时间
2.1.1 有效时间创建
2.1.2 有效时间 INSERT
2.1.3 有效时间 UPDATE 、 DELETE
2.1.4 有效时间 SELECT
2.1.5 其他
2.2 事务时间
2.2.1 事务时间创建
2.2.2 事务时间 INSERT
2.2.3 事务时间 UPDATE 、 DELETE
2.2.4 事务时间 SELECT
2.3 双时态
2.4 小结
3. DB2 : Temporal Data Management
3.1 建表
3.2 INSERT
3.3 UPDATE 、 DELETE
3.4 SELECT
3.5 其他
4. SQL Server 2016 : Temporal Tables
4.1 建表
4.2 INSERT 、 UPDATE 、 DELETE
4.3 SELECT
4.4 其他
4.4.1 数据纵向比较
4.4.2 一致性检查
5. MariaDB : System-Versioned Tables
5.1 建表
5.1.1 标准方式
5.1.2 简化方式
5.1.3 Transaction-Precise 方式
5.1.4 分区方式
5.2 动态 System Versioning
5.2.1 增加 System Versioning
5.2.2 移除 System Versioning
6. Comparison
Acknowledgments
References
系列文章
时态数据库( Temporal Database)的研究始于上世纪70年代,上世纪80~90年代理论研究发展繁荣,1993年出版的《Temporal Databases:Theory,Design,and Implementation》被称为“世界第一本关于时态数据库的专著”,是早期理论研究的标志性成果。
时态数据库发展至今,理论成果丰硕,但工业实践才刚刚起步。本文从 SQL标准和工业产品的角度展开,重点讨论时态数据库的工业成果。
我们首先简单了解时态概念(见 1. 时态概念简述 ),然后分开讨论 SQL:2011和各产品特性,最后比较SQL:2011和各个产品的异同(见 6. Comparison )。
1. 时态概念简述
介绍 SQL 标准和工业产品之前, 简单了解时态这一概念,以便下文理解。
时态是和动作、行为、事件等紧密关联的,比如 “今天阳光明媚”、“明天出差”等,天气随时间变化莫测,每个阶段有不同工作安排。这些随时间动态变化的信息,具有时态属性。
在时态数据库中,根据其刻画的维度,时间被划分为:用户定义时间、有效时间、事务时间。
1.1 用户定义时间
用户定义时间( User-defined Time ),由用户定义、解释、维护,比如:“ 20180101 ”表示“ 2018 年 1 月 1 日”、“元月廿三”表示“农历正月二十三”。数据库存储、不解释、不控制用户定义时间。
1.2 有效时间
有效时间( Valid Time ),由用户定义、赋值,由数据库存储、控制,其含义是“有效时间段内,数据在现实世界真实有效”。比如:“ 2014~2018 年就读本科”中 2014~2018 年是有效时间。有效时间也被称为应用时间( Application Time )、业务时间( Business Time )。
有效时间既可以表示过去、也能包含现在、还能预测未来,比如: “ 2018 年入学, 2022 年将本科毕业”。
1.3 事务时间
事务时间( Transaction Time),由数据库存储、解释、赋值、控制,用户可读不可写。用于记录事务何时操作数据项,刻画数据库变迁历史。比如:“2018/06/29 08:00:00时刻,新员工入职”,2018/06/29 08:00:00是事务时间。事务时间也被称为系统时间(System Time)。
事务时间的性质决定了其只能记录过去,无法记录现在,更不能预知未来。
1.4 时态数据库
时态数据库就是维护时态信息的数据库。时态数据库重点关注有效时间和事务时间,因此以这二者作为标准,将时态数据库划分为以下三种:
1. 历史数据库( Histor ical Database )
拥有有效时间属性的数据库,称之为历史数据库。历史数据库记录对象的历史状态,每条元组都有 “有效期限”。比如:历史数据库记录了“ 2014~2018 年,学历本科”、“ 2018~2021 年,学历硕士”。
2. 回滚数据库( Rollback Database )
拥有事务时间属性的数据库,称之为回滚数据库。回滚数据库记录了数据发展至今经历的事务操作、刻画出生命周期。比如:回滚数据库记录了 “ 2014/09/01 08:00:00 时刻,新生入学”、“ 2018/06/28 12:00:00 ,毕业生离校”。
3. 双时态数据库( Bitemporal Database )
双时态数据库兼具历史数据库和回滚数据库特性,刻画了数据的 “有效期限”和生命周期。
广义上,上述三种数据库都可以称为时态数据库。
2. SQL:2011 时态标准
80~90年代时态数据库研究繁荣,但缺少统一标准,经过几番波折,SQL:2011姗姗来迟。本节介绍SQL:2011时态部分的核心内容。
2.1 有效时间
从 1.2 节直观感受到,有效时间有起止,代表对象的生效和失效,以时间区间( period )刻画时间起止。
SQL:2011 中,一对 TIMESTAMP/DATE 作为有效时间区间的起止,这对列称为 application-time period 。 application-time period 采用前闭后开( closed-open )时间模型,比如:“ 2017-01-01 至 2018-01-01 保险在保”, 2017-01-01 包含在在保时间内, 2018-01-01 不在在保时间内。
2.1.1 有效时间创建
结合图 2- 1 a ) ,介绍 SQL:2011 创建有效时间的规范:
1. 创建两 DATE/TIMESTAMP 列;
2. 使用 PERIOD 语法创建有效时间区间并命名,图 2- 1 a ) 区间名为 EPeriod ;
3. 为 EPeriod 指定两 DATE/TIMESTAMP 列。
一张拥有有效时间的表,形如图 2- 1 b ) 。
2.1.2 有效时间 INSERT
有效时间表的 INSERT 语法和传统的 SQL INSERT 语法一致,如“ INSERT INTO Emp VALUES (22217, DATE ‘ 2010-01-01 ’ , ‘ 2011-11-12 ’ , 3 ”。
2.1.3 有效时间 UPDATE 、 DELETE
1. 传统 SQL UPDATE 、 DELETE 语法仍成立,如“ UPDATE Emp SET EDept=4 WHERE ENo=22217 ”、“ DELETE FROM Emp WHERE ENo=22217 ”。
2. 更新 application-time period ,如“ UPDATE Emp SET EEnd= ‘ 2012-01-01 ’ WHERE ENo=22217 AND EEnd < ‘ 2012-01-01 ’ ”。
3. 更新、删除某段有效时间的数据,结合图 2- 2 说明:
a) 以更新操作为例,如图 2- 2 b ) 所示,使用 FOR PORTION OF 关键字指定更新的有效时间段;
b) FOR PORTION OF 关键字指定的有效时间区间内的数据被更新,时间区间外的数据保持原值。如图 2- 2 a ) 和图 2- 2 c ) 所示;
c) 删除与更新类似。
2.1.4 有效时间 SELECT
1. 有效时间可以被 WHERE 筛选,如“ SELECT * FROM Emp WHERE EStart <= DATE ‘ 2011-01-01 ’ AND EEnd >= ‘ 2012-01-01 ’ ”。
2. SQL:2011 定义了多种有效时间计算方式,包括 CONTAINS 、 OVERLAPS 、 EQUALS 、 PRECEDES 、 SUCCEEDS 、 IMMEDIATELY PRECEDES 、 IMMEDIATELY SUCCEEDS ,结合图 2- 3 介绍:
a) CONTAINS time_val ,查询 time_val 时间点有效的数据;
b) OVERLAPS PERIOD (time_val1, time_val2) ,查询 time_val1~time_val2 时间段有效的数据。
2.1.5 其他
从传统数据库的角度来看,图 2- 4 没有问题,但从有效时间的角度看,“员工 22217 从 2011-02-03 到 2011-09-10 这段时间同时任职于部门 3 、 4 ”。
上面的例子引出这样一个问题:同一时间,同一对象只能有一个状态为真。为解决这个问题, SQL:2011 规范了有效时间的唯一性约束,将 application-time period 作为主键(和外键),图 2- 5 展示了如何为一张有效时间表添加有效时间约束。
2.2 事务时间
从 1.3 节直观感受到,事务时间有起止,代表着对象产生和消亡。
SQL:2011 中,一对 TIMESTAMP/DATE 列作为事务时间区间的起、止,这对列称为 system-time period 。 system-time period 采用前闭后开( closed-open )时间模型,比如:“ 2017-01-01 08:00:00 员工入职, 2018-01-01 08:00:00 员工离职”, 2017-01-01 08:00:00 时刻为公司员工, 2018-01-01 08:00:00 时刻非公司员工。
在介绍事务时间操作之前,先引入两个概念:当前行和历史行。当前行是当前数据,其 system-time period 覆盖了当前时间;历史行是历史数据,其 system-time period 是过去的时间段。
2.2.1 事务时间创建
结合图 2- 6 ,介绍 SQL:2011 规范如何创建事务时间:
1. 创建两 DATE/TIMESTAMP 列,定义为 GENERATED ALWAYS AS ROW [START | END] ,这两列由数据库维护,用户不可写;
2. 使用 PERIOD 语法创建事务时间区间,其名称固定为 SYSTEM_TIME ;
3. 为 SYSTEM_TIME 指定 ROW START 和 ROW END 列;
4. 建表带有 WITH SYSTEM VERSIONING 关键字,历史数据版本保留下来。
2.2.2 事务时间 INSERT
拥有事务时间的表,对其 INSERT 时,数据库会自动赋值 system-time period 。图 2- 7 展示了 INSERT 事务时间表的例子, Sys_start 被赋予 INSERT 发生的物理时间; Sys_end 被赋予时间类型的最大值,表示尚未改变。
2.2.3 事务时间 UPDATE 、 DELETE
事务时间表存放了当前和历史数据,当前数据可读可写,历史数据只读。更新或删除当前行,将产生并记录对应的历史行。图 2- 8 给出了事务时间表做 UPDATE 的例子,更新操作将原数据行 Sys_end 赋值为当前时间,插入新数据行,其值为更新后的值。 DELETE 操作的例子如图 2- 9 所示。
2.2.4 事务时间 SELECT
SQL:2011定义了多种事务时间计算方式,包括 FROM SYSTEM_TIME AS OF、FOR SYSTEM_TIME FROM...TO、FOR SYSTEM_TIME BETWEEN...AND,图 2- 10展示了这三种语法:
a) 事务时间点查询, FOR SYETEM_TIME AS OF time_val,用于查询time_val时间点的当前数据。
b) 事务时间段查询, FOR SYSTEM_TIME FROM time_val1 TO time_val2,用于查询system-time period包含在[time_val1, time_val2)的数据;
c) 事务时间段查询, FOR SYSTEM_TIME BETWEEN time_val1 AND time_val2,用于查询system-time period与[time_val1, time_val2)相交的数据。
另外,不带有 FOR SYSTEM_TIME关键字的查询,如“SELECT ENo, EName, Sys_Start, Sys_End FROM Emp”,查询当前数据,不查询历史数据。
查询当前和历史的全部数据, SQL形如:“ SELECT * FROM Emp FOR SYSTEM_TIME FROM ‘ 0001-01-01 00:00:00 ’ TO‘9999-12-31 23:59:59’ ”。
2.3 双时态
SQL:2011 中,兼具有效时间和事务时间的表,具备双时态属性,图 2- 11 是一个简单的例子。
1. 双时态表的创建,融合了有效时间表和事务时间表的创建。
2. INSERT 双时态表时, system-time period 中 Sys_Start 为当前物理时间, Sys_End 为其时间类型的最大值。
3. 双时态表的 UPDATE 、 DELETE 只适用于当前行,支持有效时间段上的更新和删除,并且产生一条历史记录。
4. 双时态表的查询,支持有效时间计算和事务时间计算,如图 2- 11 b ) 。
2.4 小结
SQL:2011 综合了众多时态数据库模型的优点,对现有标准做最小规模的扩展,在提供时态功能的同时,不影响现行系统。
SQL:2011 时态数据库相关规范,反映出业界对时态数据库实有需求,推进了各大数据库厂商支持时态数据库。下文将分别介绍 DB2 、 SQL Server 2016 、 MariaDB 的时态功能。
3. DB2 : Temporal Data Management
DB2 支持双时态语义,与 SQL:2011 不同的是: SQL:2011 将当前行和历史行存储在同一表(见 2.2.3 事务时间 UPDATE 、 DELETE ),而 DB2 分表存放当前数据和历史数据,图 3-1 展示 DB2 时态数据管理的概貌。
3.1 建表
DB2 创建两张表,分别存放当前数据和历史数据,结合图 3-2 ,详细介绍图 3-1 a ) 的操作:
1. 用户表建表语法基本符合 SQL:2011 规范, application-time period 被固定称为 BUSINESS_TIME 。 DB2 额外增加 TRANSACTION START ID ,用于标识不同版本是否由同一事务产生, 详细内容可参考文献 7 ;
2. 用户须手动创建历史表,与用户表结构相同。历史表与用户表分属不同表空间,一定程度上保证数据安全;
3. 历史表与用户表建立 VERSIONING 关系,之后用户表产生的历史数据将转储到历史表;
4. 虽然 DB2 双时态表由用户表、历史表共同构成,但历史表不暴露给用户读写,用户只需读写用户表即可实现历史数据读取、当前数据读写。结合下文举例,可以直观地理解这一点。
3.2 INSERT
INSERT 发生在用户表上,图 3-3 是一个例子,其中新纪录被写到用户表,历史表暂时没有记录。
3.3 UPDATE 、 DELETE
UPDATE 和 DELETE 发生在用户表上,并写历史记录到历史表,图 3-4 是 UPDATE 的一个示例。
3.4 SELECT
DB2 有效时间查询与 SQL:2011 略有不同: SQL:2011 规范了 CONTAINS 、 OVERLAPS 等七种有效时间计算, DB2 支持 AS OF, FROM...TO, BETWEEN...AND 三种有效时间计算。
DB2 事务时间查询与 SQL:2011 一致,支持 AS OF, FROM...TO, BETWEEN...AND 三种事务时间计算。
图 3-5 展示 DB2 双时态表 SELECT 的例子。
3.5 其他
SQL:2011 规范了有效时间的一致性约束(见 2.1.5 其他 ), DB2 以图 3-6 的形式提供有效时间一致性约束。
4. SQL Server 2016 : Temporal Tables
SQL Server 2016 暂不支持有效时间,只支持事务时间。与 DB2 类似, SQL Server 2016 采用当前数据和历史数据分表存放的策略,图 4-1 展示 SQL Server 2016 : Temporal Tables 概貌。
4.1 建表
SQL Server 2016 回滚表(相关定义见 1.4 时态数据库 )的创建,基本符合 SQL:2011 规范,如图 4-2 所示:
1. SYSTEM_VERSIONING = ON ,为用户表创建并绑定历史表,无需手动创建历史表、建立 SYSTEM VERSIONING 关系;
2. 绑定关系可以通过 ALTER TABLE 动态修改 ,具体内容参考文献 8 ;
3. 历史表与用户表不在同一数据库,一定程度上保证数据安全、便于权限管理;
4. 与 DB2 类似, SQL Server 2016 虽然创建了用户表、历史表,但历史表不暴露给用户读写,读写用户表即可实现历史数据读取和当前数据读写。
4.2 INSERT 、 UPDATE 、 DELETE
SQL Server 2016 : Temporal Tables 只支持事务时间,因此不存在有效时间更新、删除的场景。 INSERT 、 UPDATE 、 DELETE 同 2.2 事务时间 。
4.3 SELECT
SQL Server 2016 事务时间查询,支持 AS OF 、 FROM...TO 、 BETWEEN...AND 、 CONTAINED IN 四种事务时间计算, AS OF 同 SQL:2011 事务时间计算(见 2.2.4 事务时间 SELECT ),后三者语义略有不同。
1. FROM time_val1 TO time_val2 ,查询 system-time period 与 [time_val1, time_val2) 有交集的行,满足 SysFrom < time_val2 且 SysTo > time_val1 ;
2. BETWEEN time_val1 AND time_val2 ,查询 system-time period 与 [time_val1, time_val2) 有交集的行,满足 SysFrom <= time_val2 且 SysTo > time_val1 ;
3. CONTAINED IN (time_val1, time_val2) ,查询 system-time period 包含在 [time_val1, time_val2) 的行,满足 SysFrom >= time_val1 且 SysTo <= time_val2 。
图 4-3 展示 SQL Server 2016 : Temporal Tables 事务时间一些示例。
4.4 其他
4.4.1 数据纵向比较
基于事务时间, SQL Server 2016 提供数据纵向比较功能,其名称为“ Point in time comparison ”,图 4-4 给出一个 “与一年前部门人员架构对比”的例子。
4.4.2 一致性检查
SQL Server 2016 不支持有效时间,不存在有效时间的一致性检查。
SQL Server 2016 中,用户表和历史表的绑定是灵活的,绑定时须进行系统一致性检查,以确保回滚表结构正确、数据一致。系统一致性检查包括:
1. 架构检查,包括 “用户表和历史表列名、列数相同”、“用户表和历史表每一列对应数据类型相同”、“历史表无触发器、未配置 CDC ( Change Data Capture )”等。
2. 数据一致性检查,包括 “ SysFrom <= SysTo ”、“同一数据不同版本 system-time period 不重叠”等。
5. MariaDB : System- Versioned Tables
MariaDB 不支持有效时间,但灵活地支持事务时间。
MariaDB : System- Versioned Tables 功能的 INSERT 、 UPDATE 、 DELETE 、 SELECT 与 SQL:2011 一致,不作特别说明。重点介绍 MariaDB 事务时间表 DDL 的特性。
5.1 建表
在 SQL:2011 规范基础上, MariaDB 拓展多种事务时间建表方式,以适用于不同的应用需求。
5.1.1 标准方式
图 5-1 展示的是符合 SQL:2011 规范的,创建事务时间表的标准方式,可以发现,并未定义“历史表”, MariaDB 会将当前数据和历史数据存储在同一表中。
5.1.2 简化方式
图 5-2 展示的是 MariaDB 提供,创建事务时间表的简化方式:
1. 如图 5-2 a ) 所示,建表时无需提供 ROW START 、 ROW END 、 SYSTEM_TIME 等定义;
2. 版本信息还是会记录下来,但是 SELECT * FROM t 不会显示 system-time period 。使用特殊语法可查,如图 5-2 b ) 所示, ROW_START 和 ROW_END 含义同图 5-1 的 start_timestamp 和 end_timestamp 。
5.1.3 Transaction-Precise 方式
标准的事务时间,记录 INSERT 、 UPDATE 、 DELETE 操作发生的时刻。 MariaDB 考虑:数据行的插入、更新、删除操作有时不是立刻可见的,如长事务中的一条 INSERT ,在长事务提交后才可见。某些场景下,比如数据分析业务,写数据( INSERT 、 UPDATE 、 DELETE )发生的时间和事务提交时间之间存在的误差对分析结果的影响尚可接受,而涉及法律、证券等时,必须使用事务提交(写数据生效)时间来刻画版本的变化。
基于上述考虑, MariaDB 在 InnoDB 存储引擎上提供 Transaction-Precise 方式的回滚表,如 5-3 示:
1. system-time period 以事务 ID 作为度量;
2. 事务时间查询相应做出调整。
5.1.4 分区方式
MariaDB 可将当前数据和历史数据分区存储,如图 5- 4 所示:
1. 如图 5-4 a ) 示, 2 分区将当前数据和历史数据分区存储;
2. 如图 5-4 b ) 示, 2+ 分区在 2 分区基础上,将历史数据按 system-time period 分区。
5.2 动态 System Versioning
考虑如下场景:
1. 业务初期未计划管理历史数据,随着业务增长,历史数据管理的需求日益明显;
2. 由于存储等资源限制,无法维系大量的历史数据。
MariaDB 支持动态地调整 System Versioning ,可以为普通表增加 System Versioning ,也可以为 System- Versioned 表移除这一属性。
5.2.1 增加 System Versioning
图 5- 5 展示了如何为普通标增加 System Versioning :
1. 图 5- 5 a ) 隐式地添加 ROW START 、 ROW END ,对该表的查询见 5.1.2 简化方式 ;
2. 图 5-5 b ) 显式定义了 ROW START 、 ROW END ,对应 5.1.1 标准方式 。
5.2.2 移除 System Versioning
图 5- 6 展示如何移除 System- V ersioned 表的 System Versioning 属性。
6. Comparison
上文介绍了 SQL:2011 时态数据库相关规范,以及 DB2 、 SQL Server 2016 、 MariaDB 时态功能,本节对 SQL:2011 和上述产品对比,另外,我们将 T-TDSQL 也纳入比较。
表中 √表示“支持或符合 SQL:2011 ”,×表示“不支持”。
Acknowledgments
本项目在腾讯 TEG计费平台部立项,研究内容和实现过程得到中国人民大学 教育部数据工程和知识工程重点实验室 和腾讯公司的参与和支持,特别向项目参与人、支持者致谢。
References
[1] Haixiang Li et al. “ Efficient Time-interval Data Extraction in MVCC-based RDBMS ”. World Wide Web Journal . 2 018 , pp. 922–933.
[2] 姜晓轶 蒋雪中 周云轩 时态数据库研究进展 计算机工程与应用 2005
[3] Dharavath Ramesh, Chiranjeev Kumar: A scalable generic transaction model scenario for distributed NoSQL databases. Journal of Systems and Software 101: 43-58 (2015)
[4] 汤庸 时态数据库导论 2004
[5] Haixiang Li, Yi Feng, Pengcheng Fan. The Art of Database Transaction Processiong: Transaction Management and Concurrency Control. First edition. Beijing . China Machine Press. 2017-10-01
[6] David B. Lomet, Roger S. Barga, Mohamed F. Mokbel, German Shegalov, Rui Wang, Yunyue Zhu: Tr ansaction Time Support Inside a Database Engine. ICDE 2006: 35
[7] IBM.A matter of time: Temporal data management in DB2 10. https://www.ibm.com/developerworks/data/library/techarticle/dm-1204db2temporaldata . 2018, 6
[8] Microsoft.Temporal Tables. https://docs.microsoft.com/en-us/sql/relational-databases/tables/temporal-tables . 2018, 6
[9] MariaDB.System-Versioned Tables. https://mariadb.com/kb/en/library/system-versioned-tables/ .2018,6
系列文章
TDSQL全时态数据库系统-理念与愿景: http://blog.itpub.net/31540857/viewspace-2155687/
TDSQL-时态数据库T-TDSQL--核心技术: http://blog.itpub.net/31540857/viewspace-2155689/
TDSQL-时态数据库T-TDSQL--典型案例: http://blog.itpub.net/31540857/viewspace-2155691/
TDSQL-时态数据库T-TDSQL--功能实现: http://blog.itpub.net/31544289/viewspace-2157282/