PARADOX到底支不支持事务?(50分)

  • 主题发起人 主题发起人 boyxiang
  • 开始时间 开始时间
B

boyxiang

Unregistered / Unconfirmed
GUEST, unregistred user!
偶看了前面的关于PARADOX不支持事务的回答, 偶的DATABASE
在设置了tiDirtyRead之后, 开始事务操作. 没有任何错误,但
就是无法RollBack(不报错).
偶faint.
PARADOX到底支不支持事务?如果不支持, 好歹报个错误, 害的我
空高兴一场.
请大虾指点.
 
Paradox之类的文件型数据库都不能真正地支持事务
 
也可以说支持,也可以说不支持,
请看人家回答我的问题:


请看Delphi源代码:

//DBTables.pas:
procedure TDatabase.StartTransaction;
begin
...
if not IsSQLBased and (TransIsolation <> tiDirtyRead) then
DatabaseError(SLocalTransDirty, Self);
...
end;

procedure TDatabase.SetDatabaseFlags;
begin
...
FSQLBased := StrIComp(Buffer, szCFGDBSTANDARD) <> 0;
...
end;

//BDE.int: BDE.pas的Interface部分
const
...
szCFGDBSTANDARD = 'STANDARD';
...

也就是说
Standard类型数据库的IsSQLBased属性为False;
那么TransIsolation必须为tiDirtyRead
那还叫什么事务处理??
只不过实现了单个线程内出错后的Undo而已
我认为不过是伪事务处理。

文件型数据库本身的存取方式决定了它不可能支持事务处理,
BDE作出这么一个fake的已经很对得起观众了。

所以,将就着用吧!或者换数据库,至少换成Access
 
偶很笨, 看不懂的说.
怀蟑螂, 能解释一下吗?
所谓BDE的fake是指什么?
 
坏蟑螂的程序深刻地揭示了所谓的事务不过是BDE的一个骗局而矣
BDE需要对所有文件型的数据库其TDatabase控件的TransIsolation都设成tiDirtyRead
他说的FAKE就是指这个

事务嘛,首先要能协调不同用户对同一批数据的操作,一般说来支持
serializable/repeatable read/read commit
而DELPHI对文件数据库只支持read uncommit

其次嘛,还要能够保证数据的完整性,这就要求有事务确认与回滚的概念,而这在文件型数据
库中是不支持的。


顺便问问坏蟑螂 , 能过ADO调用ACCESS时对事务有什么特别的支持吗?
 
厚着脸皮再问:
何谓"只不过实现了单个线程内出错后的Undo而已"
及"伪事务处理"?
 
DELPHI通过BDE来实现了对一个程序来说,可以通过ROLLBACK取消刚才对数据库的操作,
但它不能够隔离不同进程间对数据的操作,所以说是伪事务操作
 
但我碰到的却连单个进程也无法rollback.
有人成功rollback过吗?
能把源程序demo mail偶一份吗?
 
还有,若是应用程序在开始了一个事务后崩溃,甚至服务器断电了,
此时的对数据的操作就不能回滚了。
Client/Server数据库中是由Database Server保证数据回滚的,
而文件型数据库则没有相就应的保证机制
 
单个进程是可以通过在程序中写 ADatabase.Rollback 来取消对数据的修改的
更详细的请看BDE32.HLP,它在/Program Files/Common Files/Borland Shared/BDE目录下

顺便说一下,我用的是Delphi5, BDE的版本是5.10
 
你要是ROLLBACK不成功,可能是BDE的版本太低,或者是你那个版本的BDE有BUG也难说,呵呵
反正我是成功的,写起来很简单的,和手册上说的没什么区别。
但你调过了ADatabase.Rollback后要对DataSet,如TTable等执行Refresh,
否则原来的数据仍然存在,可能你是少了这一步吧?
 
坏蟑螂:
引用我的东西也不写清楚,这么多马屁拍到你身上,嫉妒!
 
呵呵,蚯蚓嘛,自然是进行地下活动,不便露面的了 :)
 
smartkid, 帮偶看看程序吧
DataModule2.Database1.startTransaction;
try
with query1 do
begin
Close;
SQL.Clear;
SQL.Add('insert into table1(no1,no2) values(11,12);');
ExecSQL;

Close;
SQL.Clear;
SQL.Add('insert into table1(no1,no2) values(5,6);');
ExecSQL;
end;
DataModule2.database1.RollBack; // 为测试rollback用
except on E:exception do
begin
DataModule2.Database1.RollBack;
ShowMessage('系统出错:' + E.message);
end;
end;

query1.refresh该加在哪里呢?
 
你的Query1又不是用来显示数据用的,不用refresh
 
蚯蚓说得对,你的Query1不用调用Refresh
但要对你显示数据的那个DataSet调一次Refresh
 
但不行啊, 两条记录进去了.
偶在SQL explorer内执行
select * from table1发现都insert进去了.
 
我现在比较怀疑你的QUERY的DATABASENAME属性是不是设对了

你的Query的DatabaseName属性应设成
相应的TDatabase控件的DatabaseName,
你仔细检查一下!!
 
smartkid果然是高手.
偶把query1的databasename设错了, 设成了这个数据库的Alias name.
改过来就搞定.
启示和疑问:
1. 偶的database的alias name和databasename 是不一样的.
因为一旦改为一样, 老是报错.
但现在我把database name改为和alias name一样, 没问题了.
那么, databasename 和 aliasname是什么关系呢?
2. 偶在rollback之后再commit, 发现库中的auto increment字段
跳了几个数, 这是否意味着bde的骗局呢? 实际上那些rollback的记录
已insert进去了, 然后由于rollback, bde将其删除了.我的理解对吗?
谢谢所有热心人, 偶马上给分.
 
1)AliasName和BDE Administrator中的设置的数据库别名
2)DatabaseName是程序中设置的名称,一般说来不应该和AliasName一样,
比较合理的取名建议是_db_YourAppName ,前面加个下划线,你选取DatabaseName
时这个名字就会排得比较前,容易选些
3)Auto Increment字段的跳数我认为是很合理的,这样才能保证关键字的唯一性,
4)你对Rollback的理解是没错的,这些记录实际上已经插入了,别的进程也能看见
这些记录。
顺便说一下,要是C/S数据库,一般说来是不会将隔离级别设成DirtyRead的,
至少也得是ReadCommitted, 这样别的进程就不会看见没有Commit的数据
 
后退
顶部