乐观锁并不会使用数据库提供的锁机制
第一种:version版本号
使用版本号时,可以在数据初始化时指定一个版本号,每次对数据的更新操作都对版本号执行+1操作
version类型为int就够了,保守点用long,建议用long不出错
version = version +1 是原子化操作
第二种:时间戳来实现
你不能从web服务器取得时间,要以数据库服务器时间为准
version类型为DATETIME
version = now()
now()精度百万分之一秒,但仍然可能重复,只是概率极小。
第三种:通过生成id来实现
前两种方式,如果用ORM,都要写 raw 的代码。而且数据库改一行就要算一次当前时间或者version+1
如果直接生成id,就可以避免数据库的运算和raw麻烦的写法。
(1)用guid:
guid基本不会重复,也可以基于时间+随机生成,但是太长了
(2)用事务id:
version类型为long
事务id是自增的,一般来说要用乐观锁的地方都是有事务的。但如果有跨多个事务的话要取多次。
(3)用公共自增id:
mysql 的uuid_short函数
select uuid_short()
一台服务不够了分片的
select ((uuid_short() - 98069822578884610) << 8) | (@@server_id & 255)
postgre的Sequence序列
SELECT nextval('request_post_seq')
(4)snowflake:
好像没有必要,version 一般是hidden字段,就算上面的version的自增被看到,也只是知道request post之类的次数,应该也没什么用。
有时候需要把version给前端,用户改了数据把version提上来,version和当前数据库一样才能改数据。这种乐观锁用时间戳就好了。如果非要用公共自增又不放心,那把version对称加密下就好了。