同一个应用程序,在两台客户机上运行时,不能同时存盘(transaction deadlock)(100分)

  • 主题发起人 主题发起人 998169
  • 开始时间 开始时间
9

998169

Unregistered / Unconfirmed
GUEST, unregistred user!
[^][^]
代码:
[^]两台客户机 在同时运行同一个模块时,不能同时存盘,只有一台计机存盘成功
另一台机输入的信息丢失. 出现的错误信息如下:
A dead lock was detected ,your transaction(Process Id #29) was deadlocked
with another process and has been chosen as the deadlock victim. Return
your gerneral SOL error transaction.
请各位高手指教。以下代码错误在哪里
致谢!

我的系统配置:前台: win98 +delphi5.0 开发的应用程序
后台:winnt4.0 +SOL server 7.0
模块代码如下:
procedure TfrmDhjt.SaveBtnClick(Sender: TObject);
var
I, J, K: Integer;
s4, q1, q2, q3:String;
begin
dmHui.PostFrom:= pfDhjt;
case TADB_Dhjt of
ad_Dhjt_other:
begin
MessageBox(Handle, '未记录问题的各项资料!', '提示', MB_OK + MB_ICONWARNING)
end;
ad_Dhjt_Question:
begin
MessageBox(Handle, '未记录客户的各项资料!', '提示', MB_OK + MB_ICONWARNING)
end;
ad_Dhjt_Both:
begin
if not dmHui.dbHui.InTransaction then
dmHui.dbHui.StartTransaction;
try
{Append khzl}
q1:=edit1.Text;
q2:=edit2.Text;
q3:=edit3.Text;
dmhui.tbkhzlebsc.AsString:=dbmemo2.Text;
dmhui.tbkhzljmz.AsString:=dbmemo3.Text;
dmHui.tbkhzl.Post;

{Append dhjt}
dmhui.tbkhzl.Filtered:= False;
dmhui.tbkhzl.Filter:='xm = '+#39+q1+#39+' and qh = '+#39+q2+#39+' and hm = '+#39+q3+#39;
dmHui.tbJtdhkhh.AsInteger:= dmHui.tbkhzlkhh.AsInteger;
dmhui.tbkhzl.Filtered:= True;
dmHui.tbJtdhkhh.AsInteger:= dmHui.tbkhzlkhh.AsInteger;
dmHui.tbJtdh.FieldByName('jssj').AsDateTime:= Now;
dmHui.tbJtdh.FieldByName('jlydm').AsString:= frmLogin.sysUser;
dmHui.tbJtdh.Post;
// dmhui.tbkhzl.Post;


{Append dhcxwt}
dmHui.tbJtdh.First;
dmHui.tbJtdh.Last;
for I:= 0 to CheckListBox1.Items.Count -1 do
begin
if CheckListBox1.Checked then
begin
dmHui.tbDhcxwt.Append;
dmHui.tbDhcxwt.FieldByName('bh').AsInteger:= dmHui.tbJtdh.FieldByName('jtdhbh').AsInteger;
dmHui.tbDhcxwt.FieldByName('zxwt').AsString:= CheckListBox1.Items.Strings;
dmHui.tbDhcxwt.FieldByName('wtdm').AsString:= AnswerCodeList.Strings[0];
s4:= AnswerBm.Text;
dmHui.tbZrbm.Filtered:=false;
dmHui.tbZrbm.Filter:='bm = '+#39+s4+#39;
dmHui.tbZrbm.filtered:=true;
if not dmhui.tbZrbm.IsEmpty then
dmHui.tbdhcxwtzrbmbh.Value:=dmHui.tbZrbmbmbh.Value;
dmHui.tbDhcxwt.FieldByName('zdyda').AsString:= AnswerList.Text;
dmHui.tbDhcxwt.Post;
end
else {Unreply do with}
begin
case MessageBox(Handle, '存在未定义问题。是否将问题打印?按取消按钮取消操作', '提示', MB_YESNOCANCEL + MB_ICONWARNING) of
IDYES: begin
dmHui.tbDhcxwt.Append;
dmHui.tbDhcxwt.FieldByName('bh').AsInteger:= dmHui.tbJtdh.FieldByName('jtdhbh').AsInteger;
dmHui.tbDhcxwt.FieldByName('zxwt').AsString:= CheckListBox1.Items.Strings;
dmHui.tbDhcxwt.FieldByName('sfdy').AsString:= '1';
dmHui.tbDhcxwt.Post;
end;
IDNO: begin
dmHui.tbDhcxwt.Append;
dmHui.tbDhcxwt.FieldByName('bh').AsInteger:= dmHui.tbJtdh.FieldByName('jtdhbh').AsInteger;
dmHui.tbDhcxwt.FieldByName('sfdy').AsString:= '';
dmHui.tbDhcxwt.FieldByName('zxwt').AsString:= CheckListBox1.Items.Strings;
dmHui.tbDhcxwt.Post;
end;
IDCANCEL: begin
dmHui.dbHui.Rollback;
Exit;
end;
end;
end;
end;
for J:= 0 to CheckListBox1.Items.Count -1 do
begin
StanQuesList[J].Clear;
AnswerList[J].Clear;
AnswerCodeList[J].Clear;
AnswerBM[J].Clear;
end;

{Append hxhmtj}
// dmHui.DelQuery.Close;
// dmHui.DelQuery.SQL.Clear;
// dmHui.DelQuery.SQL.Add('Delete from Hxhmtj where khh = ' +dmHui.tbKhzl.FieldByName('khh').AsString);
// dmHui.DelQuery.ExecSQL;

for K:= 0 to CheckListBox2.Items.Count -1 do
begin
if CheckListBox2.Checked[K] then
begin
if CheckListBox2.Items.Strings[K] <> '其他' then
begin
if dmHui.tbHshmtj.Locate('tj', CheckListBox2.Items.Strings[K], [loCaseInsensitive]) then
begin
dmHui.tbHxhmtj.Append;
dmHui.tbHxhmtj.FieldByName('khh').AsInteger:= dmHui.tbkhzl.FieldByName('khh').AsInteger;
dmHui.tbHxhmtj.FieldByName('hmbh').AsInteger:= dmHui.tbHshmtjhmtj.AsInteger;
dmHui.tbHxhmtj.Post;
end;
end;
end;
end;
for I:= 0 to CheckListBox2.Items.Count -1 do
begin
CheckListBox2.Checked:= False;
end;

{Append hxcptj}
// dmHui.DelQuery.Close;
// dmHui.DelQuery.SQL.Clear;
// dmHui.DelQuery.SQL.Add('Delete from Hxcptj where khh = ' +dmHui.tbKhzl.FieldByName('khh').AsString);
// dmHui.DelQuery.ExecSQL;

for K:= 0 to CheckListBox3.Items.Count -1 do
begin
if CheckListBox3.Checked[K] then
begin
if CheckListBox3.Items.Strings[K] <> '其他' then
begin
if dmHui.tbHscptj.Locate('tj', CheckListBox3.Items.Strings[K], [loCaseInsensitive]) then
begin
dmHui.tbHxcptj.Append;
dmHui.tbHxcptj.FieldByName('khh').AsInteger:= dmHui.tbkhzl.FieldByName('khh').AsInteger;
dmHui.tbHxcptj.FieldByName('hmbh').AsInteger:= dmHui.tbHscptjtjbh.AsInteger;
dmHui.tbHxcptj.Post;
end;
end;
end;
end;
for I:= 0 to CheckListBox3.Items.Count -1 do
begin
CheckListBox3.Checked:= False;
end;

dmHui.dbHui.Commit;
{Initialize}
CheckListBox1.Items.Clear;
checkbox1.Checked:=false;
checkbox2.Checked:=false;
checkbox3.Checked:=false;
checkbox4.Checked:=false;
checkbox5.Checked:=false;
checkbox6.Checked:=false;
memo6.Lines.Clear;
Panel1.Enabled:= True;
pcData.Enabled:= False;
ListBox1.Items.Clear;
Memo1.Lines.Clear;
dbmemo2.text:='';
dbmemo3.text:='';
edit6.Text:='';
edit7.Text:='';
TADB_Dhjt:= ad_Dhjt_None;
except
dmHui.dbHui.Rollback;
end;
end;
end;
end;

 
死锁!
你的程序存在着按不同顺序更新表的问题,
 
to karxios:

谢谢你的回复!
不过,小弟对于“按不同顺序更新表的问题”还是不太明白,能否给予详细的解释!
[?]
 
好象不需要手动启动一个TRANSACTION,SQL SERVER是自动启动一个的。
或许是这里有冲突吧?

关注!!
 
某些书里说在多表的更新里客户端应该按照相同的顺序来更新。
比如客户端1里是按table1,table2,table3的顺序来更新服务器上的表,其它客户端也应该按照这
个顺序来,这样可尽量避免死锁。
 
把锁表方式改成“行锁” lock mode row
你可能使用了页锁 lock mode page
编辑时,行锁一次锁一条记录,页锁一次锁一个表
 
其实,你完全可以搞得这么复杂,如果不是特别需要,为什么非要用事务呢,不要
以为事务很好弄,这鬼东西毛病多着呢,我就经常吃亏
 
[?]各位:
我是DELPHI初学者,可手头上急需解决这个问题,请高手不嗇赐教,
能否指出此程序的具体错误所在,并提供解决的具体方法。比如说”karxios“
、”有毛病“提到的“程序存在着按不同顺序更新表的问题”,能否指出具体代码
错在哪里,哪些表的顺序存在问题。小弟实在没有找到问题所在。多谢各位!
,
 
看你的程序真费劲!不过倒看出了一点门道:
你的程序中有两处ROLLBACK,但却只有一个COMMIT。问题就在这里!
 
大家认为是死锁,但应如何解决死锁呢?
 
这样的程序我不看
 
to 203010:
程序不看,没有关系,但能否提供解决死锁的建议?
 
很简单,你用ttable控件,但是你不是在数据更新的时候才打开的,而是长连接,
所以在分布式的应用中有问题,需要在平时用只读的方式打开,
或者只用query ,这样不会有问题。
 
to zlj008:
说得有道理,但照你说的做,我需要改动程序很大(因为我急需解决问题),我的想法是,在存盘时,
检查是否有其他用户正在存盘,如果有,则等其存完后,再存盘!请问该怎样
检查其他用户正在存盘?
 
[blue]某些书里说在多表的更新里客户端应该按照相同的顺序来更新。
比如客户端1里是按table1,table2,table3的顺序来更新服务器上的表,其它客户端也应该按照这
个顺序来,这样可尽量避免死锁。[/blue]
 
后退
顶部