跳至主要內容

Klustron Limits

Klustron大约 10 分钟

Klustron Limits

Klustron分布式数据库通过使用多个服务器的计算和存储资源,可以实现上不封顶的数据管理能力,并且极大地提升了PostgreSQL和MySQL 集中式数据库的极限,让应用系统几乎不可能被实际的负载所限制。尽管如此,Klustron仍有一些极限限制。当然,大多数限制只有理论意义,实际上几乎不可能触碰到。

一个Klustron集群中的常规限制

限制项目极限值具体说明
计算节点最大数量1023
每个shard的备节点最大数量7Klustron开发团队可以按照实际用户需求增加
shard 最大数量2^24 (16M)2^N 是指2的N次方,下同。
所有shard的节点总数上限2^24 (16M)
最大客户端活跃连接数量2^32 (4G)同时受限于操作系统可用的文件句柄数和可用内存。
database和schema的最大总数均为约2^32 个同时受限于每个存储节点的数据目录所在的文件系统对目录总数的限制。
每个database中的relation 的数量上限2^32 - 系统relation数量包含数据表、索引、视图、物化视图、sequence等。同时,数据表的总数还受限于每个存储节点的数据目录所在的文件系统对文件总数以及每个目录中的文件总数的限制。系统relation数量在数百到数千个之间,下同。
一个分区表的各级分区的总数上限2^32 - N- 系统relation数量。N是这个分区表构成的树的所有内节点总数。
每个表中数据行的数量上限单表:2^48; 分区表: 约 2^80.同时受限于可用磁盘空间和文件系统允许的单文件最大字节数。
每个表可以使用的页面数量上限单表:2^32; 分区表: 2^64.同时受限于可用磁盘空间和文件系统允许的单文件最大字节数。
每个表的数据量上限(字节数)单表: 2^48; 分区表: 2^80.同时受限于可用磁盘空间和文件系统允许的单文件最大字节数。
每个表的最大page size64KB与PostgreSQL和MySQL相同;
每个表的索引数量64与MySQL的此项限制相同
每个索引的列数量16与MySQL的此项限制相同
每个表的列数量动态,见具体说明计算节点中此项理论限制为1600,同时受限于page size和具体一个数据表的已有列字段类型宽度。MySQL的Innodb引擎中此限制进一步缩减为1017,其中包括虚拟产生列。Rocksdb的索引行最大长度限制为3072字节,无索引列数量限制;Rocksdb也没有表的列数量或者行长度的限制。因此MySQL使用MyRocks引擎后,一个表的最大列数量受限于MySQL server的数据行内存buffer size(64KB) 以及具体一个表的列的数据类型和最大宽度。因此,如果一个表的列数量超出了Innodb的限制,那么可以使用myrocks引擎。
每个表的分区列最大数量32
每一种数据库对象的总数量2^32 - 少量系统relation数量数据库对象包含库、schema、表、索引、视图、物化视图、序列、以及存储过程、触发器、约束、类型、domain 等
数据库对象名称字符串最大长度63字节对应到中文大约30个字符(依照编码不同,每个中文字符占用2-4个字节)。另外,database和schema的总长度不可以多余60个字符(不是字节)。
每个text/blob字段的最大长度1GB
每个varchar字段的最大字符数动态,见具体说明受限于该列的字符集最大字节数,同时受限于该表其他列占据的空间 --- 一行所有字段共用64KB的行buffer内存空间,如果一个表的其他列使用了32KB,那么还剩下约(略小于)32KB给这个varchar列使用,如果该列的字符集的最大字节数是4(例如使用了utf8mb4字符集),那么这个varchar列的字符数最大大约8K。超过此限制时建表语句会失败。

运行时负载极限

集群全部生命周期内可执行的事务总数量

在每个shard中与Innodb和RocksDB 相同。Innodb每个行头部存储的事务ID是6字节无符号整数,也就是最大允许的事务ID是 2^48 - 1 。在内存中分配和使用的事务ID是8字节无符号整数,最大 2^64 - 1。事务ID到顶后Innodb事务子系统分发的事务ID就会回绕,但是 Innodb的代码中没有考虑如果事务ID回绕该如何处理,MySQL的文档中也未提及。虽然这个可用事务ID集合数量巨大但是理论上仍然有到顶的时候,一旦到顶后继续分配事务ID 就会回绕,导致更新的事务有更小的事务id,这样Innodb的MVCC快照隔离机制(行可见性判断机制)会失效。尽管在内存运行期这个‘顶’是 2^64 - 1,但是在undo log以及行头部存储的事务ID最大是 2^48 - 1,也就是说到了 2^48 - 1 后,继续分配的事务ID会导致Innodb系统内部事务状态混乱 --- 至少事务子系统已经无法在recovery后MVCC可见性判断机制已经无法正常工作了。

Innodb并没有做类似PostgreSQL的freeze操作。在PostgreSQL中一个事务ID最大 2^32 - 1,在当今的数据管理场景来说,回绕是必然的,极端情况下有可能每周都会回绕一次,因此freeze对PostgreSQL是一个必须的操作,也是PostgreSQL用户不得不做vacuum 并且忍受其对数据库性能的严重影响的原因之一。在Innodb中回绕几乎不可能发生,但是在一些极端场景一旦发生之后,目前MySQL并没有有效的机制来解决问题,理论上只能把全部数据重新灌入新实例。这里的极端场景之一,就是autocommit=on的时候,大量并发连接做单行的增删改。这是消耗事务ID最快的场景,这种场景下 2^48 - 1的最大事务数量限制是有可能达到的。

Rocksdb的事务ID最大为 2^64 -1, 并且也有"更新的事务ID更大" 的假设,因此也有一个回绕的理论微小可能性,并且一旦回绕那么Rocksdb(和myrocks)将无法正常工作。

假设一个Klustron集群有M个shard,在该集群运行过增删改语句的事务可能写至少一个shard,至多写M个shard,因此Klustron将一个数据库集群最多可以执行的事务总量最大扩大了M倍(相比于社区MySQL),也就更不可能发生事务ID回绕的问题。

可并发执行的活跃事务总数量

在每个shard中与Innodb和RocksDB相同,受限于Innodb和rocksdb的事务所需资源。 使用Innodb引擎时受限于Innodb 的所有undo表空间中所有 回滚段的可用的undo slots总数量open in new window,可以通过innodb_rollback_segments调节,不过默认的innodb_rollback_segments就是其最大值128。

标记位于系统表空间和所有undo表空间的所有回滚段的可用的undo slots的总数量在某一时刻为N(系统带负载运行期间N动态变化),并且集群中shard总数为M,那么此时刻集群中活跃事务的总数在[N, M*N] 这个范围,由每个事务写入的shard集合而定,此集合可能是一个shard也可能是全部shard。假如使用社区版MySQL那么M永远只能是1,因此使用Klustron可以显著增大系统可以并发执行的活跃事务总数。

在 innodb_rollback_segments=128和4KB的page size的配置下,在最坏情况下,即如果每个活跃事务都在临时表中最插入和更新,那么最大并发写事务数量只有2^14 即1万6千多个。如果数据库初始化时使用了更大的page size,(innodb_rollback_segments 最大限制为128,无法更大),那么这个上限也是相应增加。

Rocksdb没有undo log机制,它的并发执行的事务总数受限于可用内存和write_batch_max_bytes参数 ,在常见的写策略下(WRITE_COMMITTED 和WRITE_PREPARED),需要大量内存用于存储活跃事务增删改的数据行,因此如果同时有很多增删改数据量较大的事务,那么可以并发执行的事务数量也会显著降低。

每个事务中可执行的语句的数量

如果该事务包含增删改语句,那么此时计算节点限制32767个,同时在每个shard的存储节点中受限于Innodb和rocksdb的事务所需资源。

使用Innodb引擎时受限于undo表空间文件所在的磁盘可用空间和其所在的文件系统的最大文件size,把此限制记为N。如果集群有M个shard,那么集群中的总限制位于[N, M*N]之间。假如使用社区版MySQL那么M永远只能是1,因此使用Klustron可以显著增大系统可以在每个事务中执行的增删改语句数量和事务增删改数据总量。

Rocksdb没有undo log机制,但是一个事务有最大行锁数量限制(rocksdb_max_row_locks),每个事务锁住超过这么多行就会失败。并且如果 rocksdb_lock_scanned_rows=true,那么及时一行被scan后经检查不符合update语句的过滤条件,也仍然会被持续锁住,尽管在MySQL在RC模式下此情景下不符合条件的行的行锁会被自动释放。另外,Rocksdb的write_batch_max_bytes 显示了可以增删改占用的总内存空间,也就间接限制了一个事务中增删改的行的总数量。

可用内存带来的限制

当大量内外存交换发生时,数据库系统就无法提供有意义的性能,因此上两节不考虑可用内存极低导致swap频繁发生的情况。可用内存对于Innodb和Rocksdb的事务子系统运行都有诸多约束,内存消耗最大的事项,对于Innodb来说是buffer pool,除此之外之外主要是用于分配大量内部数据结构和对象所需的内存,包括打开的表,特别是事务行锁,依照事务增删改的行的数量,这项内存消耗量变化范围很大。对于Rocksdb来说主要有 memtable, block cache, 以及每个活跃事务的write batch(存储活跃事务的增删改的数据行), 另外还有事务行锁的内存消耗。Innodb的buffer pool或者Rocksdb的block cache如果频繁做页面淘汰和从外存读取,那么查询执行的性能也将慢到无法接受。

所以,假设内存已经严重不足那么系统实际已经无法提供可以接受的性能,也就是说实际有效的活跃事务数量以及每个事务中可以执行的语句数量在实际生产系统中大多数情况下比上述数值更小。

使用Klustron分布式数据库集群可以大幅提升可用内存总量,从而避免可用内存对系统中活跃事务总数以及每个事务的规模的限制。

总结

Klustron数据库大幅扩展了 PostgreSQLopen in new windowMySQLopen in new window 及其 InnoDBopen in new window和RocksDB的多项限制,可以有效避免这些限制对用于业务系统持续性造成的严重影响和长期停顿。