CockroachLabs公司的CockroachDB(简称CRDB)是一款适合于海量数据环境下高并发OLTP和OLAP场景的开源分布式NewSQL/HTAP数据库。它采用了新的架构和设计、新的分布式理论和算法,吸收了关系型数据库和NoSQL数据库各自的优点,无需应用级的分库分表,具有SQL模型的简单易用、水平弹性扩展、支持强一致性分布事务、异地多活的高可用、云原生等一系列特点。
CRDB作为新一代分布式New SQL数据库,它支持ACID事务。ANSI SQL-92 对于事务的隔离级别有明确的定义,这也是大部分传统数据库(MySQL、PostgreSQL、Oracle、DB2、SqlServer等)都遵循的标准。CRDB(PingCap的TiDB也类似)并没有完全支持ANSI标准中的所有隔离级别,它支持如下两种事务隔离级别:
- 快照隔离级别(Snapshot Isolation,简称SI)
- 串行化快照隔离级别(Serializable Snapshot Isolation,简称SSI)
SI隔离级别实现相对简单,性能较好。这种隔离级别类似于 ANSI 标准中的 "可重复读"(简称RR),但是与它又不完全相同:RR会发生“幻像读”,SI不会发生;RR不会发生“写偏斜(write skew)”,而SI会发生。在对性能要求较高,并且“write skew”对于应用不是问题的情况下可使用SI隔离级别。
相比而言,SSI实现上稍微复杂一些,但仍然能保证较高性能(读写冲突严重的情况下性能会有下降),但是不存在“写偏斜(write skew)”。在CRDB中,SSI是默认的事务隔离级别,用户须根据业务的要求以及实际性能情况,选择合适的隔离级别。
准确理解CRDB的事务隔离级别和并发控制行为是非常重要的,特别对于应用开发人员来说,如果不了解这些,那么就无法开发出正确的应用。CRDB的官方文档有对其事务的详细介绍,感觉有些复杂,而且有些地方描述含混,甚至是有笔误的地方。下面将结合一些例子对CRDB的两种隔离级别进行说明,力图简洁、清晰地让大家了解其事务隔离级别和并发控制的行为特点,希望对大家能有所帮助。本文介绍SI隔离级别,在下一篇文章中介绍SSI隔离级别。
- SI隔离级别
在CRDB中,运行在SI隔离级别的事务具有如下行为特点:
(1) 不会发生“脏读”、“不可重复读”和“幻象读”,但是会发生写偏斜。
(2) CRDB还是会在事务的运行期间,在某些情况下使用"write lock"的,所以叫做Lockless,而不是Lock free。"write lock"的生命周期是事务级的(事务提交或回滚后才释放)。在SI隔离级别下两个运行中的事务,若对相同表的相同记录进行更新,先操作的会获得"write lock",阻塞后操作的事务,直到先操作的事务提交或回滚之后锁才释放,被阻塞的事务才能继续运行;对同一行记录的读和写之间不会发生阻塞。
下面我们结合示例来进行体会(下面的示例使用的是CockroachDB 2.0.6版本):
(1) 创建用户表account并插入数据
create table account ( id int, name varchar(8), balance decimal(15,2), primary key (id) );
insert into account values(1,'user1',100) , (2,'user2',100);
(2) SI隔离级是“可重复读”的
在两个终端中,分别执行CRDB的命令行工具cockroach sql --insecure,然后在一个终端中交互式运行事务1,在另外一个终端中交互是运行事务2(在后面的示例中都是如此&