***************SQL2K,D6 C/S 我想这样,当某用户修改数据时,锁定该记录,当另一用户试图修改该记录时,则向试图修改该记录的用

  • 主题发起人 主题发起人 蛐蛐
  • 开始时间 开始时间
根本不需要任何数据库端的设置,只需要判断数据库返回的错误代码就可以了,下面
以ORACLE为例,SQL 2K的换成相应的错误代码就可以了!
Database1.Open;
Database1.StartTransaction;
try
......................(此处写更新语句)
Database1.Commit;
except
On E: EDBEngineError do
begin
Database1.Rollback;
for i := 0 to E.ErrorCount - 1 do
begin
case E.Errors.ErrorCode of
$2601:
begin
ShowMessage('呵呵!我不允许鍵值重覆!');
end;
$0021:
begin
Showmessage('太糟糕了,系统发生故障!TMD');
end;
$270b:
begin
Showmessage('对不起,你不能破坏引用完整性!怎么样,很失望吧!');
end;
$2b05:
begin
Showmessage('太糟糕了,网络连接超时判负!TMD');
end;
$0028:
begin
Showmessage('琐定违例!');
end;
$1200:
begin
Showmessage('不能识别的SQL错误!呵呵,有事干了!');
end;
$2501:
begin
Showmessage('太糟糕了,你的内存不足!请使用N(N>=10000)兆内存');
end;
$2728:
begin
Showmessage('你所操作的表不存在!');
end;
$2801:
begin
Showmessage('记录已经被其它用户琐定!');<---------------
end;
$2a06:
begin
Showmessage('数据引擎初始化错误!');
end;
$2c01:
begin
Showmessage('网络初始化失败!');
end;
$2c07:
begin
Showmessage('呜呜..呜呜!一个我不知道的网络错误,这不可能!');
end;
$2c0d:
begin
Showmessage('是谁干的!!服务器竟然没打开!');
end;
$3e07:
begin
Showmessage('初始化失败!');
end;
$3303:
begin
//ShowMessage('服务器端错误:一般的SQL错误!');
end;
else
raise EDatabaseError.Create(E.Message);
end;//case
end;//for
end;//on EDBError
on E:EFileNameError do
begin
Database1.Rollback;
end;
end;
 
袄!理解错误!原来你的信息还要包括是被哪个用户修改的!
这我没试过,但你可以分析以下数据库返回的错误中是否包含该信息
但即使有也是数据库用户的!
 
关注!sql在事务控制中,如何处理这种并发状态?[?][?]
 
最简单最实用的办法就是,再建一个表TempTable,包括实际的TableName,UserName,等可用信息,当
有人已经对他修改时,在TempTabel中插入一条记录
 
因为用SQL语句更新数据是很快的,一般都在毫秒级的时间内,然后SQL服务器一般都能
自动处理记录加锁的问题。那么蛐蛐想要知道的,恐怕不是谁正在更新/插入或者删除
数据库记录,而是谁正在屏幕前打字,准备修改某条记录吧?不知道我有没有理解错?:)

想要知道谁正在修改记录,那个正在修改记录的家伙必须自己报上名来,让大家知道。
然后为了告诉那个正在修改记录的家伙点儿什么事儿,比如发个消息什么的,你还需要
知道他的机器的IP地址。为了防止他修改数据时非法退出,你需要对这个自己设计的锁
做一个时效限制,比如说1分钟,5分钟等等。

根据上面说的,可以建立一个表,比如叫EditLock,记录正在修改的表的表名,记录ID,
用户名,用户IP,开始时间等。
记录修改的操作流程:(给定表名TableName,记录标识RecID)
1.查EditLock表,找指定时间内(比如五分钟)对TableName中RecID的修改记录。
若记录存在,转步骤7
2.向EditLock表,插入一条当前用户对TableName,RecID记录的修改记录
3.开始漫长的思考、斟酌、编辑工作
4.提交编辑结果,更新数据库
5.删除EditLock表中,刚才(步骤1中)插入的修改记录
6.完成
7.取得正在修改记录的用户名和IP地址,显示“XX用户正在修改该记录”
8.如果愿意,利用该用户的IP,向该用户发点什么消息,当然前提是他那边的程序收得到。
9.完成。
 
不主张!不又回到了FlatFile时代!l例如vfp中的RecLock(),optimistic lock.
多层无状态(Stateless)怎么办?
 
支持skyweb.up[:)][:)]
 
You can get user info from CONTEXT. Pls read HELP.
I think your Qs is the basic tech of DBMS. SQL Server use Timestamp to solve it.
I suggest you to read manuals to master DBMS theory.
 
用事务结合行锁即可完美地解决,我已经用了很久了。
 
softdog, 请给个具体例题(源代码).
 
具体源代码整理挺麻烦(偷懒!)

我把大致思路说一下:
在数据库中建立一个表:LockInfo,字段为:id int, LockTable varchar(20), LockRecID int等等
用以记录锁定信息。总体思路和skyweb描述的有点类似,但不同之处在于解锁方式,skyweb用的是手工
的方法,还要考虑客户端非正常断开时的情况。我的方法是这样的:
(说明:下面的描述语句是类SQL描述,不是真正的SQL语句)

锁定表:
LockInfo.BeginTrans
insert LockInfo(LockTable, LockRecID) values(表名, 记录ID)

判断锁定:
if exists(select id from LockInfo where LockTable=@LockTable and LockRecID=@LockRecID with nolock)
message: 已经被其他用户锁定(如果LockInfo表有足够的信息,可以检测到什么用户锁定)
else
message: 没有锁定

解锁:
LockInfo.RollbackTrans

大致思路:
某个客户端对数据库(MSSQL)中某个表进行修改之前如果开始了一个事务,则数据库会进行行锁,
即阻止其他用户存取该记录,但如果其他用户用“脏读”的方式来读取,则也可以看到该记录(修改后),
这样,在锁定时开始一个事务,并在LockInfo表中插入一条记录,此时不提交或回滚。如果其他用户用
“脏读”的方式能读取到该记录,则说明有锁定相应的表中的记录。当执行锁定的用户解锁时,只需回滚
事务即可。
在这种方式下,如果执行锁定的客户端非正常断开,数据库会自动回滚,相当于该客户端执行了解锁
操作。

对于数据库的事务和锁定我也只是懂点皮毛,上面的方法在大量客户端时不知会不会产生事务上的问题。
欢迎大家讨论!
 
还可以up的吧
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部