关于记录锁定的解决方案

伍子V5 2011-06-02 03:26:06
WEB应用程序,在多人同时操作同一条记录时,容易发生相互覆盖。
我们的系统采用的是悲观锁,每一条记录都加USER_ID和DATETIME数据项,当一个人进入编辑画面时,首先检查USER_ID是否为空,如果不为空,表明该记录被别人正编辑,不能进入;为空,则允许进入编辑画面,并且更新USER_ID为当前用户,DATETIME为当前时间。退出编辑画面时,则清空USER_ID和DATETIME。现在的主要问题就是退出编辑画面比较难捕获。用的是onunload事件,但很多时候用户通过一些非正常途径退出应用就不会触发这个事件。
不知道大家对解除锁定有没有别的办法能让它更稳定一些?或者对这种锁定机制有没有好的更好的处理办法?
...全文
174 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
toury 2011-06-03
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 letsflytogether 的回复:]

to:toury

我现在所做的WEB应用,以前的方式是大家通过共享来共同完成一个EXCEL,现在把它做成在线的方式。

感觉你说的这个方案,与我现在使用的,有点类似于乐观锁与悲观锁的区别
我现在使用的,是悲观锁,类似于VSS,只要编辑就锁定数据,这样就不至于冲突。
你提供的方案,是乐观锁,类似于CVS,在提交时判断是否冲突。如果里面有一个合并功能就更好了,但恰恰这个是很难做的。
……
[/Quote]
1、你也可以将我的建议称之为“乐观锁”。但我之所以没说乐观锁是因为,通常乐观锁只是简单的将控制字段version +1,也就是说,提交更新数据时,只检查新version 是否比原version 的版本号高。而我的建议已经从这个功能上加了附加功能。 至于你说的“如果里面有一个合并功能就更好了,但恰恰这个是很难做的。”我不认同。合并有什么难做的?如果你的业务逻辑已经确定清楚,完全可以把7楼“c)覆盖前个用户的更改(此人要有高权限);”这个改为“合并”。这个问题靠说很难说清楚,不说了。

2、如果是EXCEL编辑,不知道你们是不是使用的微软最新WEB OFFICE控件做在线编辑。如果是,在控件里找找保存时有没有说明可以利用的,我没仔细研究过。你不妨试试
伍子V5 2011-06-03
  • 打赏
  • 举报
回复
to:toury

我现在所做的WEB应用,以前的方式是大家通过共享来共同完成一个EXCEL,现在把它做成在线的方式。

感觉你说的这个方案,与我现在使用的,有点类似于乐观锁与悲观锁的区别
我现在使用的,是悲观锁,类似于VSS,只要编辑就锁定数据,这样就不至于冲突。
你提供的方案,是乐观锁,类似于CVS,在提交时判断是否冲突。如果里面有一个合并功能就更好了,但恰恰这个是很难做的。

当然,乐观锁性能更高一些,但考虑的东西也很多,实现起来比较麻烦。
toury 2011-06-03
  • 打赏
  • 举报
回复
7楼的一个好处是:
如果用户A进入编辑界面后出差去了,三天没关电脑,一点也不影响其他人的编辑工作。只不过等他回来继续编辑好后,提交时会得到可能几十条的更新数据,那就让他小子自己慢慢看去好了,哈哈
toury 2011-06-03
  • 打赏
  • 举报
回复
我说的“策略有问题”不是指怎么锁定的问题,而是该不该“锁定”的问题。你把注意力放在前者我觉得是治标,考虑后者才是治本。当然,也许是我猜错了你的需求,呵呵。

太晚了,我没精力过多描述对你需求的猜测,大致说说我的建议:
1、你现在的业务逻辑:
“每一条记录都加USER_ID和DATETIME数据项,当一个人进入编辑画面时,首先检查USER_ID是否为空,如果不为空,表明该记录被别人正编辑,不能进入;为空,则允许进入编辑画面,并且更新USER_ID为当前用户,DATETIME为当前时间。退出编辑画面时,则清空USER_ID和 DATETIME”;

2、我建议的业务逻辑:
1) 每一条记录都加VERSION_LOG数据项,内容为(USER_ID||DATETIME||更改的数据id);这个更改的数据id含义下面会提及;
2) 可同时编辑。当几个人进入编辑画面时,读出原数据以及VERSION_LOG送到客户端。于是出现“各干各的”状况;
3) 总有一个人先完成编辑,需要将数据送到服务端进行数据更新。关键点在此:提交前,先AJAX(参数为编辑前的VERSION_LOG)到服务器,检查一下VERSION_LOG,看看USER_ID||DATETIME有没有更新。如果没有,没的说,服务端返回OK给该用户的客户端,那么,本次编辑的数据由这个用户提交服务器,写库。写库时,最好先不要更新数据,而是将数据另外存入一个临时表,然后将临时表的该数据的id放入VERSION_LOG,这样就可以用新的USER_ID||DATETIME||更改的数据id 来更新VERSION_LOG;
4) 第二个人完成编辑后,同样先AJAX(参数为编辑前的VERSION_LOG)请求服务器的VERSION_LOG,发现VERSION_LOG变了,则以更改的数据id取得前个用户的编辑数据返回给第二个用户的客户端显示出来,让他自己斟酌怎么处理,给出几个选择:
a)前面的合理,放弃自己的;
b)坚持我的,还要上传;
c)覆盖前个用户的更改(此人要有高权限);
a没的说;b、c需要你们自己去论证如何处理
5)以此类推,第三个人AJAX,把前两个人的编辑后的数据返回给他,同4)....
6)如果出现几个人各持己见,那就由他们的大佬最后定夺。。。。
========================
顺便说个小例子,不知道是不是对你有启发:
一个文本文件,你同时用记事本和ultraEdit打开,当你先在基本里更改并保存后,转到ultraEdit后,会跳出提示。。。。虽然和你的需求不太搭,但可参考。强调一下,上面说的条理也不清楚,仅仅是个建议。
豆虫 2011-06-02
  • 打赏
  • 举报
回复
这个问题我觉得其实就是个超时的问题 我的想法是这样的:
在Client端可以增加系统服务时间配置(可以指定管理员来配置,也可以所有人都可配置)
然后前台需要的地方发ajax或是定时去发请求 这个视情况而定
服务端获取这个当前的配置来进行处理 超过了这个时间的话解除锁定也好或是发什么消息也好 总之能够达到效果就行

在下愚见,希望不吝指教。
伍子V5 2011-06-02
  • 打赏
  • 举报
回复
to: toury

所以向大家请教有没有更好的办法,因为现在手头的项目是多人共同编辑一些数据,所以相互覆盖的几率很大,必须要有锁定机制。

to: net_lover,hookee

你们说定时器的办法,以前在做在线人员的时候用到过。用定时器一直更新着时间,如果超过了多长时间就视为退出。当时感觉在线人员就很费资源,只不过一个系统一般就一个,所以就没有计较。如果每一个编辑页面都这样,是不是太繁琐了一点。

服务器端服务,是个办法,但超过多长时间就视为退出呢?是个比较难确定的,毕竟操作有快有慢。太短,可能别人还没有操作完,太长,那种由于非正规途径退出的锁定的时间又太长了。
hookee 2011-06-02
  • 打赏
  • 举报
回复
1 服务器端做一个服务,定时检查某个更新时间,如果超时一段时间就认为断线, 清空数据
2 客户端 做一个定时计数器, 检测是否有操作(比如,跟踪鼠标或键盘事件), 有清空计数,
计数没超过值,则定时向服务器端更新时间,超过一定值,则发短线消息.
孟子E章 2011-06-02
  • 打赏
  • 举报
回复
如果想要的更准确,可以使用ajax+定时器之类的方法去更新状态。
孟子E章 2011-06-02
  • 打赏
  • 举报
回复
你应该设置一个时间限制,比如,1小时内状态没有改变,则认为此人已经放弃编辑了。
toury 2011-06-02
  • 打赏
  • 举报
回复
且不说“退出编辑画面比较难捕获”,你不觉得这个策略有问题吗?如果一个用户进入编辑画面,然后出去办事一天,那这条记录就一天也不能被别人编辑了?

87,910

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧