Amazon Aurora Design Considerations for High Throughput Cloud Native Relational Databases

󰃭 2024-08-24

写在最前 当你特别在乎性能, 找到一个良好抽象的概念, 打破它, 把脚伸进泥潭里. 传统的数据库都基于posix语义的文件系统来设计的. 当我知道我要在挂着EBS的EC2上跑数据库, 后面还有S3给我做备份, 一切都可以重新设计. 这就是云原生的魅力吧. Background 这二年都上云, 云上都玩儿存算分离. 存算分离导致了数据库服务的磁盘IO负载瓶颈变成了网络IO负载瓶颈, 但为了高可用又到处复制还是搞得写放大严重. 而且为了数据一致性一些同步操作, 二阶段提交(2PC, Two Phase Commit)等操作更是对性能影响严重. Aurora践行日志流即数据库的思想, 通过只持久化预写日志(WAL, Write Ahead Log, 和MySQL中的redo log是一个概念)减少写放大. 还通过单写实例模式避免复杂的共识问题. 设计思想 集群容错 第二章这部分也是分布式系统的老话了, 熟悉这个领域的人一看就懂. 说的其实就是 Quroum + Segmentation (文中称一组复制为PG, Protection Group). Quorum模型, 即在分布式系统中, 每份数据副本都有一票, 共$V$票. 读写操作都需要保证获得的票数大于最小票数限制才可以进行操作. 虽小票数限制要保证: 1.$V_{read} + V_{write} \gt V$; 2. $V_{write} > \frac{V}{2}$. 规则1保证了数据不会被并发读写, 也就保证了读的时候可以读到至少一份最新的数据. 规则2保证了两个写入操作不会同时发生, 这两条规则保证了数据的串行化. 至于Segmentation, 无非就是将上述读写操作的对象拆分(或聚合)成合理的大小, 使之成为系统中检测失效和修复的最小单元. 讨论故障恢复时有两个常见概念: 平均故障发生时间(MTTF, Mean Time to Failure) 和平均故障修复时间(MTTR, Mean Time to Repair).

Continue reading 


Partitions

󰃭 2024-08-22

-- Create a new database CREATE DATABSE par; postgres=# select pg_database.oid, pg_database.datname from pg_database; oid | datname -------+--------------- 5 | postgres 16388 | testdump 1 | template1 4 | template0 16395 | partitiontest 24592 | testdb 24649 | par postgres=# \c par You are now connected to database "par" as user "postgres". par=# CREATE TABLE foo ( id int not null, name VARCHAR(50), amount INT NOT NULL ) PARTITION BY RANGE(amount); CREATE TABLE par=# CREATE INDEX idx_amount ON foo(amount); CREATE INDEX par=# select pg_relation_filepath('foo'); pg_relation_filepath ---------------------- (1 row) par=# \d foo Partitioned table "public.

Continue reading 


MVCC in PostgreSQL

󰃭 2024-08-22

/* * LOCKMODE is an integer (1..N) indicating a lock type. LOCKMASK is a bit * mask indicating a set of held or requested lock types (the bit 1<<mode * corresponds to a particular lock mode). */ typedef int LOCKMASK; typedef int LOCKMODE; /* * These are the valid values of type LOCKMODE for all the standard lock * methods (both DEFAULT and USER). */ /* NoLock is not a lock mode, but a flag value meaning "don't get a lock" */ #define NoLock 0 #define AccessShareLock 1 /* SELECT */ #define RowShareLock 2 /* SELECT FOR UPDATE/FOR SHARE */ #define RowExclusiveLock 3 /* INSERT, UPDATE, DELETE */ #define ShareUpdateExclusiveLock 4 /* VACUUM (non-FULL), ANALYZE, CREATE * INDEX CONCURRENTLY */ #define ShareLock 5 /* CREATE INDEX (WITHOUT CONCURRENTLY) */ #define ShareRowExclusiveLock 6 /* like EXCLUSIVE MODE, but allows ROW * SHARE */ #define ExclusiveLock 7 /* blocks ROW SHARE/SELECT.

Continue reading 