ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

ScyllaDB CQL UPDATE 语句完全指南:语法、原子性、条件更新与冲突解决

2026/9/14 12:40:23 拓冰建站 浏览量
ScyllaDB CQL UPDATE 语句完全指南:语法、原子性、条件更新与冲突解决 ScyllaDB CQL UPDATE 语句完全指南语法、原子性、条件更新与冲突解决【免费下载链接】scylladbNoSQL data store using the Seastar framework, compatible with Apache Cassandra and Amazon DynamoDB项目地址: https://gitcode.com/GitHub_Trending/sc/scylladb导读本文以 ScyllaDB CQL 官方文档中的UPDATE语句参考docs/cql/dml/update.rst为主体系统讲解在 ScyllaDB 中如何更新行数据包括完整的 BNF 语法、SET赋值语义计数器自增、集合/UDT 子元素更新、USING更新参数TIMESTAMP/TTL/TIMEOUT、IF条件更新及其底层 Paxos 代价以及同时间戳冲突时 ScyllaDB 的单元格级冲突解决算法。读完本文你将能够写出正确、高效的UPDATE语句并理解其与关系型数据库UPDATE的本质差异。一、UPDATE 语句概述与 SQL 的关键差异在 ScyllaDB 的 CQL 中更新一行数据通过UPDATE语句完成。其核心特征与 SQL 有显著差异WHERE子句必须包含全部主键列where_clause用于选中要更新的行必须覆盖构成PRIMARY KEY的所有列非主键列则通过SET关键字赋值。默认不检查行的存在性与 SQL 不同UPDATE默认不检查行是否已存在除非使用IF条件——如果行原本不存在则直接创建它如果已存在则更新它。同时没有任何办法得知本次操作是创建还是更新。同一分区键内的更新是原子性的一个UPDATE语句中对同一分区键的所有修改要么全部生效要么全部不生效。跨节点无协调并发更新与INSERT类似在不同集群节点上并发执行的UPDATE不需要协调由语句携带的最高时间戳决定哪个单元格值胜出。从语法解析器的实现看ScyllaDB 的updateStatement规则定义在 cql3/Cql.gUPDATE后依次跟随表名、可选的usingClause、一个或多个SET赋值、WHERE子句以及可选的IF条件最终构建一个raw::update_statement对象。二、完整语法与 BNF 定义官方参考语法如下update_statement: UPDATE table_name : [ USING update_parameter ( AND update_parameter )* ] : SET assignment ( , assignment )* : WHERE where_clause : [ IF ( EXISTS | condition ( AND condition )*) ] update_parameter: ( TIMESTAMP int_value | TTL int_value | TIMEOUT duration ) int_value: ( integer | bind_marker ) assignment: simple_selection term : | column_name column_name ( | - ) term : | column_name list_literal column_name simple_selection: column_name : | column_name [ term ] : | column_name . field_name condition: simple_selection operator term对应到源码cql3/Cql.g 中的解析规则为( usingClause[attrs] )?可选的USING子句其中usingTimeoutConcurrencyClause还额外支持TIMEOUT与CONCURRENCY参数见 cql3/Cql.gK_SET columnOperation[operations] (, columnOperation[operations])*SET赋值列表K_WHERE wclausewhereClauseWHERE子句( K_IF (K_EXISTS ... | conditionsupdateConditions ...) )?可选的IF EXISTS或条件表达式列表。两个典型示例-- 示例 1带 TTL 的多列更新 UPDATE NerdMovies USING TTL 400 SET director Joss Whedon, main_actor Nathan Fillion, year 2005 WHERE movie Serenity; -- 示例 2计数器自增 UPDATE UserActions SET total total 2 WHERE user B70DE1D0-9908-4AE3-BE34-5573E5B09F14 AND action click;三、SET 赋值的三种形态与约束SET子句支持三类赋值对应文档中的assignment规则1. 普通赋值column term最简单也最常用的形式将任意非主键列设置为给定值。注意源码会在预处理阶段严格校验SET中出现主键列会直接报错。在 cql3/statements/update_statement.cc 中prepare_internal检查def-is_primary_key()时抛出PRIMARY KEY part ... found in SET part同一列被多次设置且操作互不兼容时如先SET a 1再SET a a 1抛出Multiple incompatible setting of column错误cql3/statements/update_statement.cc引用了表中不存在的列名会抛出Unknown identifiercql3/statements/update_statement.cc。2. 计数器自增/自减c c 3与c c - 1号前后的列名必须相同自增/自减仅允许作用于计数器列counter而且这是计数器唯一允许的更新操作由于源码中UPDATE语句要求完整聚簇键require_full_clustering_key()返回true见 cql3/statements/update_statement.cc对计数器行的更新必须指定完整的PRIMARY KEY。关于计数器本身docs/cql/types.rst 给出了重要限制计数器列不能是PRIMARY KEY的一部分一张表中若包含计数器列则除主键外的所有列都必须是计数器类型计数器不支持 TTL 过期计数器更新不是幂等的若计数器更新因超时或连接丢失而失败客户端无法得知更新是否已被应用重放更新可能造成重复计数overcount。3. 集合与 UDT 子元素更新id id some-collection向集合追加元素如tags tags {new}属于列表、集合、映射等集合类型的专用更新形式详细说明见 docs/cql/types.rst 的 Collections 章节id[value1] value2更新映射map中某个键对应的值id.field 3设置**非 frozen 用户自定义类型UDT**中某个字段的值。这些集合/UDT 更新操作在源码中由cql3/lists.hh、cql3/maps.hh、cql3/sets.hh、cql3/user_types.hh等对应的setter/adder等操作类实现并在raw::update_statement::prepare_internal中通过operation-prepare(db, keyspace(), *def)完成类型校验与操作构造cql3/statements/update_statement.cc。四、USING 更新参数TIMESTAMP、TTL 与 TIMEOUTUPDATE支持通过USING指定三个更新参数INSERT、DELETE、BATCH对其中部分参数同样适用完整说明见 docs/cql/dml.rst参数取值类型说明默认行为TIMESTAMP整数或绑定标记为操作设置写入时间戳单位为微秒自 Unix 纪元起未指定时由协调节点在语句执行开始时取当前时间微秒作为时间戳TTL整数秒为写入的值设置生存时间到期后自动从数据库中删除默认永不过期TTL 0等价于无 TTL若表设置了default_time_to_liveTTL 0可清除值的 TTLTIMEOUTduration为特定请求设置超时时间参考SELECT的USING TIMEOUT章节-- 同时使用多个参数必须用 AND 连接 UPDATE NerdMovies USING TIMESTAMP 1436261307989000 AND TTL 400 SET director Joss Whedon WHERE movie Serenity;关于TIMESTAMP的几个实践要点ScyllaDB 保证同一协调节点产生的查询时间戳是唯一的即使跨同一节点上的不同 shard但不同节点分配的时间戳不保证全局唯一高写入速率下时间戳碰撞并不罕见一旦发生将交由冲突解决算法决定哪个单元格胜出详见第六节显式使用USING TIMESTAMP时应用应保证提供的时间戳值唯一否则同样会触发冲突解决。注意在 cql3/statements/modification_statement.cc 中若语句带有IF条件且同时显式设置了TIMESTAMP实现会进行相应处理——条件更新LWT与自定义时间戳的组合需要谨慎使用。五、IF 条件更新乐观锁与 Paxos 代价默认UPDATE不检查行的存在性但可以通过IF在若干列上附加条件只有条件满足时行才会被更新-- 仅当该行存在时才更新 UPDATE NerdMovies SET director Joss Whedon WHERE movie Serenity IF EXISTS; -- 带多条件用 AND 连接的更新作为乐观锁使用 UPDATE UserActions SET total total 2 WHERE user B70DE1D0-9908-4AE3-BE34-5573E5B09F14 AND action click IF total 10;需要特别强调的性能事实来自官方文档使用IF条件会引入不可忽视的性能开销内部会使用 Paxos 协议因此应谨慎使用。从实现看IF条件的存在会让语句走轻量级事务LWT路径在 cql3/statements/modification_statement.cc 中带条件的修改语句会检查 serial consistency 并执行 Paxos 协商流程以实现跨副本的原子读-比较-写。另外一个值得注意的约束来自 cql3/statements/update_statement.cc使用列表达式赋值如col col 1时必须配合 LWT 条件如IF col ! NULL或IF EXISTS否则预处理阶段会直接抛出SET with a column expression ... requires an LWT condition错误——这是为了保证读-改-写操作的原子性避免并发更新丢失。六、更新排序与时间戳冲突解决单元格级的最高时间戳胜出INSERT、UPDATE、DELETE操作按TIMESTAMP排序排序在单元格cell级别进行每个单元格携带写入时间戳、过期属性非零 TTL 时以及单元格值。基本规则是时间戳最高的单元格胜出。时间戳冲突的来源良性冲突replay客户端重试或内部进程重放导致的重复变更单元格等价任意选择即可并行查询冲突不同协调节点基于各自本地微秒时间计算出相同的写入时间戳用户显式指定冲突应用通过USING TIMESTAMP提供了不唯一的时间戳。冲突解决算法由于各副本必须对冲突达成一致否则读修复会不断产生仍然冲突的新单元格永远无法收敛ScyllaDB 实现了内部一致的冲突解决算法按如下属性依次比较排序单元格是 tombstone墓碑/删除标记还是存活单元格单元格是否带有过期时间单元格的TTL最终才比较单元格携带的值。这部分内容与冲突解决算法的完整文档位于 docs/cql/dml.rst。从代码结构看该算法实现在 ScyllaDB 的单元格合并/墓碑处理路径中并可能在版本演进中调整。如何获得可靠的一致性可靠序列化使用唯一且单调递增的写入TIMESTAMP原子性保证使用轻量级事务LWT确保INSERT、UPDATE、DELETE的原子性。七、源码级执行流程小结一条UPDATE语句在 ScyllaDB 中的完整生命周期可以总结为解析cql3/Cql.g 中updateStatement规则解析语句生成raw::update_statement预处理raw::update_statement::prepare_internalcql3/statements/update_statement.cc校验列名、主键约束、赋值兼容性、IF条件与列表达式的 LWT 要求构造出cql3::statements::update_statement执行update_statement继承自modification_statement通过execute_operations_for_keycql3/statements/update_statement.cc对目标行的每个列操作逐一应用到 mutation 上若带IF条件则进入 Paxos/LWT 路径落盘与复制mutation 携带时间戳与 TTL 属性按分区键原子写入并复制到副本最终由单元格级时间戳决定并发写冲突的胜者。八、相关文档导航数据修改语句总览与更新参数/更新排序的公共章节docs/cql/dml.rstINSERT语句参考docs/cql/dml/insert.rstDELETE语句参考docs/cql/dml/delete.rstBATCH批量语句参考docs/cql/dml/batch.rst计数器类型与限制docs/cql/types.rst集合类型说明docs/cql/types.rstTTL 专题文档docs/cql/time-to-live.rstCQL 语法解析器源码cql3/Cql.gUPDATE 语句实现cql3/statements/update_statement.cc【免费下载链接】scylladbNoSQL data store using the Seastar framework, compatible with Apache Cassandra and Amazon DynamoDB项目地址: https://gitcode.com/GitHub_Trending/sc/scylladb创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考