数据库字段规范及乐观锁常见错误

2016-07-06  本文已影响0人  里昂的夏天

一、背景

统一关系数据库中,每张表必须包含的字段(称为系统字段),便于统一数据库开发规范,便于大数据抽取数据等;

二、系统字段定义

  1. 字段名标准
    1. 字段名统一采用英文
    2. 字段名要完整,准确,尽量避免简写(state/status、tid/cid/uid/aid...)
    3. 字段名不要含有无意义的前缀(p_uid/l_cid/a_order)
    4. 不同单词之间用‘_’字符分隔
  2. 必有字段
名称 类型 可空 默认值 说明
id bigint 无符号,自增,主键;业务量小可选择 int 型
sys_version int 第一次插入值为 0,之后乐观锁维护原则
create_pin varchar(50) 只有第一次插入时维护为当前操作人
create_time datetime now() 只有第一次插入时维护
update_pin varchar(50) 每次更新都要记录当前操作人
update_time datetime now() 每次业务更新都取 DB 当前时间 now()即可
yn tinyint 0:有效,可维护,1:已逻辑删除,只能查询
udt timestamp CURRENT_TIMESTAMP DB 自动维护,用于大数据抽数,不维护

三、乐观锁维护原则

  1. 使用版本号的乐观锁 SQL 如下:

update tab_xxx
set column1=#{field1Value}, column2=#{field2Value},...
sys_version=sys_version+1, update_pin=#{updatePin}, update_time=now()
where
id=#{id} and sys_version=#{sysVersion} and yn=0

  1. 程序处理流程如下:

    1. 判断SQL更新影响行数。如果为 0,说明这条数据已经被其它线程更新,并发更新失败
    2. 反查数据。因为乐观锁导致,更新条数为0时(并发更新)要反查数据,如果已经改为目标结果,返回“已被他人执行成功”的结果,不能直接返回失败,也不能直接返回成功。
    3. 重试更新操作。具体重试采取系统再次取数据后更新的方式,还是提示给客户重新操作的方式,每个系统视具体场景而定。
  2. 常见问题:

    1. 有sysVersion却在update语句里没体现
    2. sql体现了sysVersion,在程序里没对更新结果条数做判断
    3. 对更新结果条数做了判断,但是只要条数为0就抛异常(实际可能已经被其它线程执行成功),没有就地反查比对结果
    4. 就地反查比对结果了,当前状态和预期状态一致就返回执行成功,没有告知是其它线程执行成功的,导致当前线程的调用方认为是自己执行成功的,进而执行后续逻辑(实际已经被其它相同逻辑的线程执行过)。
上一篇下一篇

猜你喜欢

热点阅读