一路走来,OceanBase 始终坚持自主研发,去年双11正式对外发布的OceanBase 2.2 版本为内外部业务提供了很多新增的功能。与此同时,事务引擎也在持续迭代,推出了可串行化隔离级别、复制表、闪回等重要更新。本文将对OceanBase 2.2版本中事务引擎的三大重点功能分别进行介绍。
举个例子来说明两者的特性。下图演示在 Read Committed 隔离级别下,事务内可以见到别的事务修改完成的数据。
Session 1 | Session 2 | 备注 |
CREATE TABLE A (pk INT PRIMARY KEY, val INT); INSERT INTO A VALUES(1, 1); INSERT INTO A VALUES(2, 2); COMMIT; | 准备数据 | |
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; | Session 1 开启 Read Committed 隔离级别事务 | |
SELECT * FROM A; +----+------+ | PK | VAL | +----+------+ | 1 | 1 | | 2 | 2 | +----+------+ | ||
INSERT INTO A VALUES(3, 3); COMMIT; | Session 2 插入一条数据并提交 | |
SELECT * FROM A; +----+------+ | PK | VAL | +----+------+ | 1 | 1 | | 2 | 2 | | 3 | 3 | +----+------+ | Session 1 的 SELECT 语句是 Read Committed 隔离级别,会重新获取“读快照版本” |
下图演示在 Serializable 隔离级别下,事务内不能见到别的事务修改完成的数据。
Session 1 | Session 2 | 备注 |
CREATE TABLE A (pk INT PRIMARY KEY, val INT); INSERT INTO A VALUES(1, 1); INSERT INTO A VALUES(2, 2); COMMIT; | 准备数据 | |
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; | Session 1 开启 Serializable 隔离级别事务 | |
SELECT * FROM A; +----+------+ | PK | VAL | +----+------+ | 1 | 1 | | 2 | 2 | +----+------+ | ||
INSERT INTO A VALUES(3, 3); COMMIT; | Session 2 插入一条数据并提交 | |
SELECT * FROM A; +----+------+ | PK | VAL | +----+------+ | 1 | 1 | | 2 | 2 | +----+------+ | Session 1 的 SELECT 语句是 Serializable 隔离级别,使用事务开启时获取的“读版本号”,不会读到后续事务的修改(3,3) |
应用如何选择 Read Committed 还是 Serializable 隔离级别没有一招鲜的策略,需要从实际需要出发。通常来说,Read Committed 可以满足大部分应用场景的需求。同时,Serializable 隔离级别为了支持事务级别的快照能力,可能会引发更大概率事务调度异常,最终导致并发的事务执行无法满足可串行化隔离级别,出现回滚。下面的例子描述了一种无法串行化的报错。
Session 1 | Session 2 | 备注 |
CREATE TABLE A (pk INT PRIMARY KEY, val INT); INSERT INTO A VALUES(1, 1); INSERT INTO A VALUES(2, 2); COMMIT; | 准备数据 | |
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; | Session 1 开启 Serializable 隔离级别事务 | |
SELECT * FROM A; +----+------+ | PK | VAL | +----+------+ | 1 | 1 | | 2 | 2 | +----+------+ | ||
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; SELECT * FROM A; +----+------+ | PK | VAL | +----+------+ | 1 | 1 | | 2 | 2 | +----+------+ UPDATE A SET VAL = VAL + 1 WHERE PK = 2; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 SELECT * FROM A; +----+------+ | PK | VAL | +----+------+ | 1 | 1 | | 2 | 3 | +----+------+ COMMIT; | Session 2 开启 Serializable 隔离级别事务,更新 PK = 2 这一行数据,之后提交 | |
UPDATE A SET VAL = VAL + 1 WHERE PK = 2; ERROR-08177: can't serialize access for this transaction | Session 1 也更新 PK = 2 这一行数据,结果不是 VAL 值被更新为 4,而是会出现“can't serialize”报错 |
功能二:实时一致的复制表
OceanBase 的分布式架构从本质上决定了数据被分散在不同的机器上分别服务,SQL 语句执行时会根据所操作数据的位置生成最优的执行计划,或在一台机器或在多台机器运行 SQL 的执行计划。
虽然 SQL 引擎会根据最优的策略来优化执行的开销和执行的时间,但是涉及多台机器数据的操作时,跨机器之间的数据传输很多时候不可避免。例如很多业务中存储关键信息的配置表,还有金融业务中存储汇率信息的表。
这类表格内的数据被频繁访问,通过网络被反复的传输到各台机器上,带来的开销有时很大,而这种开销可以通过“复制表”功能来优化。复制表将需要被频繁访问的数据复制到集群的每一台机器上,反复的操作不需要再跨机传输数据。
TPC-C 测试模型中有一张商品(ITEM)表,这张表的内容是测试所模拟的销售公司所有售卖的商品信息,包含了商品的名字、价格等信息。“订单创建”事务执行中需要请求这张表内的数据来确定订单的价格信息,这样的商品表也是复制表可以优化的典型场景。
将数据复制到多机带来的最大挑战是对于数据的修改要在所有机器上实时生效,否则一部分机器读到新的数据另一部分读到旧的数据,这一定是不满足用户需求的功能。OceanBase 使用特殊的广播协议保证复制表的副本一致性,当复制表发生修改时,所有的副本会同时修改。并且,只有在所有机器上的副本都修改成功时,修改操作才会生效。
在分布式系统中,另一个棘手的问题又会出现,如果复制表修改的过程中有机器出现故障,故障机器上的复制表的副本无法修改,那么复制表就再也不能改了吗?如果不解决这个问题,复制表在出现机器故障时就会拖累用户的操作。
OceanBase 采用了租约机制来解决这个难题。每台机器上有效的复制表副本都会获得租约,当复制表修改时,修改要同步到所有有租约的副本。如果出现机器故障,故障机器上的复制表副本的租约会失效,失效的副本不会被同步新的修改,所以不会阻塞复制表后续的修改操作。失效的副本同时会拒绝读取操作,保证不会读到旧的数据。当失效副本恢复后,可以追赶遗漏的数据,等其追赶到最新状态后会被重新授予租约。
OceanBase 事务引擎的多版本并发控制机制是通过修改操作产生新的数据版本来实现,这个机制除了可以解决事务并发控制的需求,还能够支持其他很多功能,比如指定快照版本查询的能力可以用于查看历史数据,兼容 Oracle 的 Flashback Query 功能。
用户可以在 SELECT 语句中使用 AS OF 关键字来指定需要读取的历史版本,支持使用 SCN 和 TIMESTAMP 两种方式。使用 SCN 指定事务提交版本号,使用 TIMESTAMP 指定一个具体的时间戳。而 OceanBase 允许用户回溯的历史时间通过 UNDO_RETENTION 变量来指定,OceanBase 会保留 UNDO_RETENTION 时间内的所有历史版本。
语句 | 备注 |
CREATE TABLE A (pk INT PRIMARY KEY, val INT); INSERT INTO A VALUES(1, 1); | 准备数据 |
SELECT * FROM A; +----+------+ | PK | VAL | +----+------+ | 1 | 1 | +----+------+ | 表 A 内的实际数据 |
SELECT * FROM A AS OF TIMESTAMP TO_TIMESTAMP('2010-05-11 22:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF'); Empty set | 指定一个插入数据之前的时间戳不会读到数据 |
SELECT ORA_ROWSCN, PK, VAL FROM A; +------------------+----+------+ | ORA_ROWSCN | PK | VAL | +------------------+----+------+ | 1273590000000000 | 1 | 1 | +------------------+----+------+ | 使用 ORA_SCN 伪列可以查看行上事务的提交版本号,1273590000000000 是微秒级时间戳,对应 2010-05-11 23:00:00.000000 |
SELECT * FROM A AS OF TIMESTAMP TO_TIMESTAMP('2010-05-11 23:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF'); +----+------+ | PK | VAL | +----+------+ | 1 | 1 | +----+------+ | 使用 2010-05-11 23:00:00.000000 这个时间戳就可以查询到数据 |
立即申请免费体验OceanBase 2.2版本
「 OceanBase 2.2 版本 」正式上线官网啦!OceanBase 2.2版本是成功支撑2019年天猫双11大促的稳定版本,同时也是用于TPC-C测试且荣登TPC-C性能榜首的版本。OceanBase 2.2版本除了在蚂蚁金服和网商银行广泛使用外,目前也在部分金融机构中使用。 想要立即体验「OceanBase 2.2版本」? 免费获取链接: https://oceanbase.alipay.com/download/resource(或点击下方阅读原文) 如果你在安装和使用的过程中遇到问题且希望跟OceanBase一线专家进行技术交流,我们为开发者用户提供了两种渠道: 1)加入OceanBase技术交流钉钉群,打开钉钉搜索群号:21949783(备注:OB 2.2) 即可加入 2)扫描下方二维码添加OB小助手微信号(备注:OB 2.2)通过验证后拉您进入OceanBase 2.2版本交流群 我们非常重视来自每一位开发者用户的体验和心得,希望能够获得你们的宝贵反馈。
● OceanBase 2.2 版本上线啦!立即申请即可免费体验
▼内容这么棒,还不赶紧扫码关注一下!▼
点击“阅读原文”即可免费体验OceanBase 2.2版本