SQL无内置数据版本号机制,需通过ROWVERSION类型或整型version字段配合应用逻辑实现行级版本控制,用于乐观并发与变更追踪。

SQL 本身不提供内置的“数据版本号”机制,所谓“标识数据版本”,实际是指在应用层或数据库设计中,**主动为数据行添加可追踪变更的标记**,常见做法是加字段(如 version、row_version)并配合特定策略更新。直接查 @@VERSION 或 SERVERPROPERTY 得到的是数据库引擎版本,不是你某条订单或用户记录的版本。
用 ROWVERSION(SQL Server)自动标识行级变更
SQL Server 提供 ROWVERSION(旧称 TIMESTAMP)数据类型,它不是时间戳,而是一个数据库范围唯一、自动递增的二进制值,每次更新行时由系统隐式更新:
- 插入新行时自动生成初始值;更新该行时,值自动变为下一个全局唯一值
- 适合做乐观并发控制:UPDATE 时 WHERE 条件带上原
rowversion值,若不匹配说明已被他人修改 - 不能手动插入/更新,不能作为主键或索引键(除非加上
NOT NULL),也不支持算术运算 - 示例建表:
CREATE TABLE orders (id INT PRIMARY KEY, amount DECIMAL(10,2), ver ROWVERSION);
用整型 version 字段 + 应用层控制
这是跨数据库通用的做法,但需应用逻辑保证原子性和一致性:
- 字段类型通常为
INT或BIGINT,初始值设为 1,每次更新时SET version = version + 1 - 必须用单条 UPDATE 语句完成(避免先 SELECT 再 UPDATE 的竞态):
UPDATE products SET price = 99.99, version = version + 1 WHERE id = 123 AND version = 5;
- 检查
@@ROWCOUNT是否为 1,为 0 表示版本冲突,需重试或报错 - 注意:MySQL 在严格模式下不允许在同一个语句中引用并更新同一字段(如
SET v = v + 1是允许的,但某些旧版本有例外)
为什么不用 datetime 或 last_modified 当版本标识?
时间字段直观,但不适合作为“版本标识”的核心依据:
- 高并发下可能产生相同时间戳(尤其毫秒级精度不足时)
- 无法区分同一毫秒内多次修改(比如批量脚本反复更新)
- 时钟回拨、跨服务器时区/同步误差会导致顺序错乱
- 它反映的是“何时改”,而非“改第几次”——而版本控制的核心是序号性与不可重复性
- 若真要用时间,建议搭配序列号(如
CONCAT(FORMAT(GETDATE(), 'yyyyMMddHHmmss'), '_', NEXT VALUE FOR version_seq)),但复杂度陡增
真正容易被忽略的是:**版本字段是否参与业务逻辑校验**。比如金融类系统要求每次资金变动必须带前序版本号,否则拒绝执行;而日志类表可能只用 ROWVERSION 做简单并发防护。选哪种方式,不取决于“哪个更高级”,而取决于你的事务粒度、并发强度和回滚需求——没做幂等或版本比对的应用,加了 version 字段也等于没加。










