在分布式数据库中,序列(Sequence)和全局事务号(Global Transaction ID, 常称 GTID/Timestamp)是两个相关但截然不同的概念,这是一个核心且容易混淆的问题。它们都涉及唯一标识符的生成,但目标、作用域和实现机制有本质区别。本文今天重点学习之。

1. 核心概念与作用
|
特性 |
序列 (Sequence) |
全局事务号 (GTID/Timestamp) |
|
本质 |
业务标识生成器 |
事务时序协调器 |
|
主要目标 |
生成全局唯一的业务标识符 (如订单号、用户ID) |
为事务提供全局唯一的、严格时序化的标识 |
|
使用者 |
应用层 (INSERT 语句、业务逻辑) |
数据库内核 (事务管理器、存储引擎、复制模块) |
|
关键要求 |
唯一性、趋势递增 (可选)、高性能 |
全局唯一性、严格单调递增、线性一致性 |
|
可见性 |
业务可见 (通常作为表的主键或业务字段) |
数据库内部使用 (对业务透明) |
2. 关键区别
(1)目的与作用
序列:解决“如何给新数据分配唯一ID”的问题。例如:
INSERT INTO orders (order_id, ...) VALUES (NEXTVAL('order_seq'), ...);生成的order_id是业务数据的一部分。
全局事务号:解决“如何确定事务发生的先后顺序”和“如何保证数据一致性”的问题。它用于:
1.多版本并发控制(MVCC):确定数据的可见性版本 (哪些事务能看到哪些版本的数据)。
2.分布式事务提交:为跨节点的事务分配一个全局认可的提交时间戳。
3.数据复制(Change Data Capture, CDC):按事务顺序复制数据,保证副本一致性。
4.全局快照隔离:提供一致的读视图(SELECT ... AS OF TIMESTAMP txid)。
(2)时序性要求
序列:不要求严格全局时序。它通常只需要保证趋势递增(如Snowflake)或局部连续(如分段分配)。不同节点生成的ID在全局视角下可能是交错的。
示例:节点A生成ID=100, 节点B生成ID=101, 节点A再生成ID=102。ID=101 的事务可能比 ID=102 的事务后提交。
全局事务号:必须严格全局单调递增,并反映事务的真实提交顺序。它是整个数据库系统的“逻辑时钟”。
要求:如果事务TX1 在 TX2 之前提交,那么GTID_TX1 < GTID_TX2 必须成立。这是实现线性一致性和隔离级别的基石。
(3)性能与协调开销
序列:追求高性能、低延迟。机制如分段分配、Snowflake 的核心思想就是最小化协调开销(甚至无协调)。允许一定的“不连续”和“时间偏差容忍”来换取性能。
全局事务号:生成必须强协调,通常由中心化的时间戳授予服务(TSO - Timestamp Oracle)或分布式逻辑时钟协议 (如 HLC - Hybrid Logical Clock)实现。
每次事务提交(尤其是分布式事务)都需要获取全局时间戳,可能成为瓶颈。高性能实现是其关键挑战。
(4)实现机制 (典型方案)
序列:
1.分段分配(Segment Allocation)
2.Snowflake 及其变种 (如 百度 UIDGenerator, 美团 Leaf)
3.UUID (v4, 但通常不推荐作主键)
4.数据库内置序列(如 PostgreSQLSEQUENCE, OracleSEQUENCE, 需分布式扩展)。
全局事务号(GTID/Timestamp):
1.中心化TSO:
(1)TiDB:使用 Placement Driver (PD) 作为 TSO 服务,分配单调递增的时间戳。
(2)Google Spanner:使用 GPS 和原子钟实现的TrueTime API提供有界误差的全球时间,结合 MVCC 时间戳。
2.分布式协议:
(1)CockroachDB:使用Hybrid Logical Clocks (HLC)。HLC = 物理时钟 (NTP同步) + 逻辑计数器。物理时钟用于高效推进,逻辑计数器解决同一物理时间内的顺序问题。
(2)Amazon Aurora:使用存储层维护事务日志的全局顺序。
(3)Paxos/Raft 日志索引号:在某些设计中,事务的提交日志在共识协议中的位置 (Log Index) 可以作为一种全局有序的事务ID。
3. 两者的关联性
虽然本质不同,但它们在分布式数据库中紧密协作:
1)数据行标识:一个表的主键(可能由 Sequence 生成) 会与多个事务号关联。每次对该行的更新都会产生一个新版本,并标记上创建它的事务开始时间戳和删除/覆盖它的事务提交时间戳(MVCC)。
2)数据定位:在按主键分片(Sharding) 的数据库中,Sequence 生成的主键值可能隐含了分片信息 (如 Snowflake 的 Worker ID 部分)。GTID 则用于协调跨分片的事务。
3)一致性读取:当应用使用Sequence 生成 ID 并插入数据时,该数据只有在插入事务提交后(其 GTID 生效)才对其他指定了大于等于该 GTID 的快照的事务可见。
4. 区别表
|
特征 |
序列 (Sequence) |
全局事务号 (GTID/Timestamp) |
|
角色 |
业务数据标识生成器 |
事务时序协调器 |
|
目标 |
生成唯一业务ID |
保证事务全局顺序与一致性 |
|
严格时序要求 |
不要求 (趋势递增即可) |
必须严格单调递增 |
|
协调开销 |
尽量低 (分段缓存/Snowflake本地) |
必然高 (TSO/HLC/Paxos) |
|
使用者 |
应用程序 |
数据库内核 (事务管理、存储、复制) |
|
业务可见性 |
(常作为主键/业务字段) |
(通常对应用透明) |
|
典型实现 |
分段分配、Snowflake、UUID |
TSO (TiDB/Spanner)、HLC (CockroachDB) |
文章总结:
序列= 给“东西” (数据行) 起名字的规则。保证名字不重复,最好能大概看出谁先来后到。
全局事务号= 给“事件” (事务提交) 排队的号码牌。必须严格按照事件发生的真实顺序发号,不能乱。
文章至此。
1154

被折叠的 条评论
为什么被折叠?



