全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1174
推到 Plurk!
推到 Facebook!

多人使用下如何安全动态创建数据表?

缺席
mustapha.wang
資深會員


發表:89
回覆:409
積分:274
註冊:2002-03-13

發送簡訊給我
#1 引用回覆 回覆 發表時間:2006-09-14 10:59:45 IP:210.22.xxx.xxx 訂閱

如果系统是多人使用同一个数据库,程序需要动态建立数据表,要求为:

1、如果存在就不要创建了;

2、不存在才创建。

我们先作试验,创建的SQL如下:

if exists (select * from dbo.sysobjects where id =
object_id(N'[dbo].[wxhtest]') and OBJECTPROPERTY(id,
N'IsUserTable') = 1)
drop table [dbo].[wxhtest]

CREATE TABLE [dbo].[wxhtest] (
[ProcessOID] [int] IDENTITY (1, 1) NOT NULL ,
[ProcessOIDParent] [int] NOT NULL ,
[ProcessAID] [varchar] (16) NOT NULL ,
[Name] [varchar] (64) NOT NULL ,
[Category] [varchar] (64) NULL ,
[ExecType] [int] NOT NULL ,
[ExecMode] [int] NOT NULL ,
[ExecName] [varchar] (64) NULL ,
[ArgumentList] [varchar] (512) NULL ,
[LevelNumber] [int] NOT NULL ,
[SortNumber] [int] NOT NULL
) ON [PRIMARY]

ALTER TABLE [dbo].[wxhtest] WITH NOCHECK ADD
CONSTRAINT [PK_wxhtest] PRIMARY KEY
CLUSTERED
(
[ProcessOID]
) ON [PRIMARY]

ALTER TABLE [dbo].[wxhtest] ADD
CONSTRAINT [DF_wxhtest_ProcessOIDParent]
DEFAULT (1) FOR [ProcessOIDParent],
CONSTRAINT [DF_wxhtest_Name] DEFAULT
('Name') FOR [Name],
CONSTRAINT [DF_wxhtest_Type] DEFAULT (0)
FOR [ExecType],
CONSTRAINT [DF_wxhtest_Mode] DEFAULT (0)
FOR [ExecMode],
CONSTRAINT [DF_wxhtest_LevelNumber]
DEFAULT (1) FOR [LevelNumber],
CONSTRAINT [DF_wxhtest_SortNumber]
DEFAULT (1) FOR [SortNumber]

CREATE UNIQUE INDEX [IX_wxhtest] ON [dbo].[wxhtest]
([ProcessAID]) ON [PRIMARY]

在一个循环里面反复执行这样的SQL,会先判断是否存在,存在就drop,然后再建。开启连个以上的exe执行,一会儿就会报“表wxhTest已经存在”的错误。因为判断和创建会被打断,A刚刚drop,B刚好就判断为没有表,A创建,然后B也创建,就出错了。

procedure TForm1.Button1Click(Sender: TObject);
var
n:integer;
begin
ADOConnection1.Open;
Stop:=false;
n:=0;
while not Stop do
begin
ADOConnection1.Execute(Memo2.Text);
Sleep(5);
ADOConnection1.Execute(Memo1.Text);
Sleep(1);
Application.ProcessMessages;
Inc(n);
Edit1.Text:=InttoStr(n);
end;
end;

如果我们再加上Transaction,看是否有改善。

procedure TForm1.Button1Click(Sender: TObject);
var
n:integer;
begin
ADOConnection1.Open;
Stop:=false;
n:=0;
while not Stop do
begin
ADOConnection1.BeginTrans;
try
ADOConnection1.Execute(Memo2.Text);
Sleep(5);
ADOConnection1.Execute(Memo1.Text);
ADOConnection1.CommitTrans;
except
ADOConnection1.RollbackTrans;
Raise;
end;
Sleep(1);
Application.ProcessMessages;
Inc(n);
Edit1.Text:=InttoStr(n);
end;
end;

开启3个exe,跑一会儿,还是出现错误“事务(进程ID55)与另一个进程已被锁死在Lock资源上,且该事务已被选作死锁牺牲品。请重新运行该事务。”

------
江上何人初见月,江月何年初照人
mustapha.wang
資深會員


發表:89
回覆:409
積分:274
註冊:2002-03-13

發送簡訊給我
#2 引用回覆 回覆 發表時間:2006-09-14 11:16:23 IP:210.22.xxx.xxx 訂閱

我想问题还是一样的,就是判断和创建会被别的Transaction打断,跟一般的线程冲突一样,就决的方法是加锁,在Transaction完成前,不能让别的Tranaction来读sysobjects表。比如:

procedure TForm1.Button1Click(Sender: TObject);
var
n:integer;
begin
ADOConnection1.Open;
Stop:=false;
n:=0;
while not Stop do
begin
ADOConnection1.BeginTrans;
try
ADOConnection1.Execute('select * from sysobjects with (TABLOCK,UPDLOCK)');
Sleep(5);
ADOConnection1.Execute(Memo2.Text);
Sleep(5);
ADOConnection1.Execute(Memo1.Text);
ADOConnection1.CommitTrans;
except
ADOConnection1.RollbackTrans;
Raise;
end;
Sleep(1);
Application.ProcessMessages;
Inc(n);
Edit1.Text:=InttoStr(n);
end;
end;

开启3个exe执行良久没有错误。因为锁了整个表,执行起来感觉明显慢了。

这种方法是否是大家常用的方式或应该使用的方式呢?

------
江上何人初见月,江月何年初照人
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#3 引用回覆 回覆 發表時間:2006-09-14 12:19:30 IP:61.229.xxx.xxx 未訂閱
你好,不知为何你需要不停的drop table,然后再create,是什么目的?

为何不使用 truncate table,这样index和identity也会回复。

或者用delete dbcc CHECKIDENT。

不知你是否因为 Idenitity的问题所以才drop 又create?

当然你最后的那个lock sys table的方式是可行的,但非必要的话还是找别的方法达成想要的目标。
------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
mustapha.wang
資深會員


發表:89
回覆:409
積分:274
註冊:2002-03-13

發送簡訊給我
#4 引用回覆 回覆 發表時間:2006-09-14 13:19:46 IP:210.22.xxx.xxx 訂閱

谢谢回复。我的需求开始就讲了,只是看某个表是否存在,如果不存在就创建,然后加一数据进取。因为是多人使用,所以可能会出现那样的冲突,使程序出现错误。

试验是模拟这种情况,因为要反复试验,所以表要drop掉,不然只能模拟一次,很难发现问题。

但是,我把最后一种加锁的方法跑久一点,还是会出现前面看到的死锁错误。怎么办?

------
江上何人初见月,江月何年初照人
系統時間:2024-06-26 22:28:19
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!