数据库表字段设计小白问题

心塞塞,昨儿提了个解决方案被否了,理由是不符合产品设计规范;
需求如下:表里想设计一个状态字段status,这个状态包括的值有:1设计,2变更,3执行等,然后由于并发的问题,需要给状态加锁的标志位,意思就是并发状态下,有一人在执行时,先给状态加锁,其他人就不能对该条数据进行其他相关操作了。
我的方案是:状态列设计为两位的存储方式,第一位用来表示状态的使用值,第二位用来表示是否锁住,类似于10表示设计状态下没有锁,11表示设计状态下加锁。我觉得没有必要再加一个字段去标识是否加锁,数据库本身的字段就很多了,而且我认为这锁状态和原有状态是一种组合的方式。
这种一个字段多位的处理方式在我之前几家公司都有用到过。可是这里却说这样的设计不符合规范。
我查了数据库设计规范,第一范式要求属性具有原子性,不可拆分,难道说我这样的设计是不符合第一范式的要求?
望大牛指点~

PS:申明一点,就是数据库锁,一开始我提的方案也是用数据库锁,但是数据库锁会有几个问题:
第一就是如果用数据库的锁,在两人同时修改提交的时候,肯定会有一个人的修改被退回导致操作被浪费,这是业务上不允许的;
第二就是业务上并不是只操作一张表,执行阶段操作的并不是主数据本身,而是他的一些附表;我们是想通过在主表上加锁字段来判断这条数据的其他附表操作是否可以被做;

还有我最想问的是,多位存储状态的列设计是否不符合数据库设计

8个回答

你是把业务所需要的操作和数据库操作混一起考虑了。业务状态的值和变更依赖于业务逻辑处理,数据库的锁依赖于数据库。
可以考虑把业务状态加个锁定的值。如设置锁定为4,你的表里肯定有一些数据字段,设为data吧,可以类似:
update table1 set data='data...', status='4' where id='xxx' and status='1'
操作修改提交,一步就把数据和状态修改了。

这种情况再提交一定失败,因为status不再是1。然后你再考虑其他状态什么情况发生和处理,比如审核操作可以把status再改为1或者2,或者3。

feelcycle_07
默默悟问 一个方法、属性做多种用途,都不提倡,资源受限情况另说;操作不方便,如果你只是要查询/更改/查和改某一位,依赖于是否数据库是否支持
一年多之前 回复
lexuansweet
流年轻描淡写的伤 回复feelcycle_07: 我就没考虑用数据库锁啊,我现在是在疑惑 锁状态字段和业务状态字段 为什么不能统一成一个字段的多位存储去体现;是不符合数据库设计规范吗
一年多之前 回复
lexuansweet
流年轻描淡写的伤 回复feelcycle_07: 你说的很对
一年多之前 回复
feelcycle_07
默默悟问 不允许浪费的说法要依赖业务保证,如果两个人员同时打开一个项目,只是查询应该都是可修改,不想浪费修改操作,那就得考虑开始修改就加锁,但是取消操作撤锁就麻烦了,如果网页关了或者机器崩溃了,这个锁就挂那了,还得考虑怎么处理。
一年多之前 回复
lexuansweet
流年轻描淡写的伤 我就没考虑用数据库锁啊,我现在是在疑惑 锁状态字段和业务状态字段 为什么不能统一成一个字段的多位存储去体现;是不符合数据库设计规范吗
一年多之前 回复
feelcycle_07
默默悟问 回复lexuansweet: 我的意思是你必须在业务状态上下功夫,而不是考虑数据库锁能帮你,数据库锁只能保证修改那一下的互斥安全。你要不让人修改必须设置状态为不可修改,而且页面提前显示,以免“浪费”。
一年多之前 回复
lexuansweet
流年轻描淡写的伤 锁状态也是业务逻辑处理时的隐含状态,它只是想防止并发操作的问题,如果把所状态也加到业务状态中的话,就会导致业务状态没有了,比如说在变更的时候锁上了,把状态改成了4锁定,但之前的2变更状态就显示不了了,等锁定完了,也不知道之前是哪个状态了,所以我不想在原有状态中新增锁状态
一年多之前 回复

应该是不符合公司内部的产品设计规范---单个字段其含义具有唯一性,跟第一范式是两码事了。
你这样一来,单个字段其实包括两个含义,要求程序员读取后再解析,不符合贵公司内部产品设计规范。

其实你要么直接加一个字段,估计就符合产品设计规范了。
如你所说,已经有很多列了,则可以将表拆分;依业务逻辑将此表拆成多个表,由外键关联;至少可以节约存储空间了。

至于锁定,你即使增加了一个字段,也需要加锁了。要不并发时,一个想改成1,一个想改成2,这种事情也是会发生的了;这称之为数据库锁。
至于将字段置为已经锁定,则称之为业务逻辑锁了,是由程序员控制的了。
只要有可能并发,并且需要适应这种情况,则两把锁都是要的了。

weixin_41986182
weixin_41986182 回复lexuansweet: 字段含议具有唯一性,当然有好处。1、SQL语句简单(想想假如要select出所有的被锁定的记录)。2、数据库中的值直接就看得懂,不用对着说明书看。3、所有数据库的select实现算法做了足够的优化,性能不会有什么影响。4、万一以后业务有扩充不能程序判断,而必须SQL语句直接判断,扩充方便,如通过该字段进行两个表的关联select。
一年多之前 回复
weixin_41986182
weixin_41986182 字段含议具有唯一性,当然有好处。1、SQL语句简单(想想假如要select出所有的被锁定的记录)。2、数据库中的值直接就看得懂,不用对着说明书看。3、所有数据库的select实现算法做了足够的优化,性能不会有什么影响。4、万一以后业务有扩充不能程序判断,而必须SQL语句直接判断,扩充方便,如通过该字段进行两个表的关联select。
一年多之前 回复
weixin_41986182
weixin_41986182 回复lexuansweet: 公司的产品设计规范当然包括数据库设计,还是重要部份了。
一年多之前 回复
lexuansweet
流年轻描淡写的伤 然后我想问下,产品设计规范还包括数据库表的设计吗?数据库表的设计不是应该有开发人员自己设计吗
一年多之前 回复
lexuansweet
流年轻描淡写的伤 你说的单个字段其含义具有唯一性,从大的方向来说,都是存的状态字段,虽然包含了业务状态和锁状态两部分,但其实锁状态是一种附加状态,设计成两个字段固然能解决问题,但同样需要两个字段组合起来判断,这也是需要程序员解析的;甚至比一个字段的解析更费时间和性能;两把锁肯定是都需要的,但是我觉得放一个字段里通过多位存储更能简化业务。
一年多之前 回复

还是加一个字段吧,采用乐观锁的方式!

如果是并发问题,直接用数据库的锁就行了,不必要在添加一列作为锁的标志。数据库本身就是有锁的,在有人操作数据的时候加一个锁就行了

sinat_28984567
二月十六 回复lexuansweet: 把这些操作都放到一个事务里,这个事务执行完所有操作,其他等待事务再执行
一年多之前 回复
lexuansweet
流年轻描淡写的伤 回复sinat_28984567: 业务上第一个执行完,业务上是不能直接释放锁的,还有其他很多操作,这样的话,在数据库层加锁就会有问题啦,
一年多之前 回复
sinat_28984567
二月十六 回复lexuansweet: 提交修改在一个事务里,其他事务操作会等待现在占用资源的事务结束之后,再执行
一年多之前 回复
sinat_28984567
二月十六 回复lexuansweet: 不会浪费的,会等待第一个执行完之后再执行
一年多之前 回复
lexuansweet
流年轻描淡写的伤 我知道,我一开始也是这么和他们说的,但是他们说这样会有一种情况就是并发正好有两个人同时修改提交,会有其中一个人的操作被浪费,所以要提前用锁去控制,一个人在发修改请求时,先锁上,其他人再发请求就不让修改了。
一年多之前 回复

对某一行或者某个表都可以加锁,看题主需求加一个TABLOCKX 即可
SELECT * FROM 表 WITH (TABLOCKX)

weixin_39905589
weixin_39905589 很好很不错
一年多之前 回复
lexuansweet
流年轻描淡写的伤 我知道,我一开始也是这么和他们说的,但是他们说这样会有一种情况就是并发正好有两个人同时修改提交,会有其中一个人的操作被浪费,所以要提前用锁去控制,一个人在发修改请求时,先锁上,其他人再发请求就不让修改了。
一年多之前 回复

我建议,字段要有其关键意义,锁定应该优先于状态字段,如果使用同一字段在交叉操作数据时锁定会有问题。

如你之前设计 1 ;2;3 ;10 ;11; 数据处理的判断逻辑会出问题,在流程以及其他业务处理时字段值唯一比较有利于操作。

lexuansweet
流年轻描淡写的伤 我的意思是,之前没有加锁是1,2,3,如果要加上锁,则在之前的状态后面再加一位,表示锁的状态,设计后,就只有10,11,20.21这样的状态了,
一年多之前 回复

数据库本身就是有锁的啊

通过事物的隔离级别控制

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!