在数据库操作中采用多线程操作的问题(100分)

  • 主题发起人 主题发起人 mycwcgr_bak
  • 开始时间 开始时间
M

mycwcgr_bak

Unregistered / Unconfirmed
GUEST, unregistred user!

有一个数据库 aa.dbf ,在VCL中有一个 query1 从 aa.dbf 中查询记录,并在
前台对query1进行增加,修改,删除操作。现计划使用一个后台线程,使用query2
从aa.dbf中查询记录,并对查询到的每一个记录做复杂的计算,其计算结果写入该
记录的某个字段中。
我认为:上述的模型有一些问题,在后台对query2中的记录进行处理时,这些记录
可能被前台的query1修改,甚至删除了,或者前、后台程序同时对一个记录操作,出
现死锁,您认为是不是这样,如果上述模型不成立,应该如何建立模型。
 
使用lookup字段!
 
使用lookup字段!
 
如果你的记录没有重复的话。
用conn直接执行select,update的任务。
在独立的线程中进行复杂的计算处理,然后用:
conn.exec('update table set field=xxx where 唯一条件);
唯一条件是指能够唯一识别你刚才处理的记录的标识,如果该记录被删除了也不会出错。
你可以在表结构中添加一个表明是否已经经过计算的标识,在那个单独的线程中不停地进行
查找、计算、更新的操作。查找是指查找没有经过计算的记录:
select top 1 * from table1 where calcfield is null
计算
update table1 set calcfield=xxx where 唯一条件
其中calcfield是你用来存放计算结果的字段,如果没有计算的话它应该是null
 
先查询记录,线程计算,计算完成,添加记录时,使用lock锁住数据库,添加完毕,
用unlock解锁,就应该可以了。
 
原来听到人说多线程操作数据库,当时我以为听错啦,现在总算知道真的有这么一说
 
不知道大虾们是不是对线程格外的喜好!
象这种对数据库的运算操作,还使用Thread,真有点。。。
对于单用户数据库,完全可以将运算写在记录插入、修改 COMMIT之前。
如果是网络数据库,要对该记录做实时、准确的运算操作,
是否可以考虑在数据库后台使用行级TRIGGER,触发语句为UPDATE[、INSERT]。
 
感谢: hhzh426
不过,您的方法不能处理两个线程同时更新一个记录可能引起的死锁,并且
此算法很浪时间。

感谢:zhuny
不过:对于"单用户数据库,完全可以将运算写在记录插入、修改 COMMIT之前"
恐怕不能认同。因为计算很复杂,如不使用线程在后台运行的话,前台
将不能对程序作任何操作。
 
你的问题是经典的临界数据同步问题。
在每个线层里加入对当前数据库记录的state的判断可以解决。
 
如果使用两个线程,最好为每个线程分配一个TSESSION 和TDATABASE,这样可以避免一些问题
 
>>处理两个线程同时更新一个记录可能引起的死锁
你试过吗?
conn.exec('update table set field=xxx where 唯一条件)执行时如何锁定记录应该是由
数据库自己决定的,与你没有什么关系吧。
>>浪费时间
可能是吧,不过你说过要进行复杂的计算,总不能将很多记录同时取出来进行计算吧,还是
一个记录一个记录的处理比较好,最好是将记录取出来后存储在变量中进行计算(在此同时
将对数据库的连接中断)
 
通过TQuery组件在后台进行查询,但要注意下面两点:
1.每个线程化的查询必须在它自己的会话中。为此,需要把一个TSession组件加到窗体上,
然后设置TQuery的SessionName属性为TSession的名称。这样,如果TQuery组件通过TDataBase
组件连接数据库时,必须保证每个会话所使用的TDatabase对象是唯一的;
2.当一个辅助线程打开了查询后,TQuery组件就不能与TDatasource组件有任何联系。
否则,查询必须在主线程内进行。这是因为:TDatasource的作用是把查询的结果与用户界面相
关联,而涉及到用户界面的操作必须在主线程内进行。
 
请自己结束吧
 
大家看清楚了,他用的是<b>dbf</b>数据库
>是否可以考虑在数据库后台使用行级TRIGGER
dbf中怎么实现TRIGGER?
>执行时如何锁定记录应该是由数据库自己决定的,与你没有什么关系吧。
dbf会自己处理锁定?

 
我同意 hqiang的观点 。其实此问题没有必要用线程处理,或许您偏好吧。我们用线程处理
程序是根据一定条件的,在delphi 中线程处理问题还不太完善 。
若线程处理,只要在线程中计算前对query1 的状态进行判断后再处理,另外不要用
query2,在create线程时重载create函数,在线程中定义一个tquery变量,计算直接对
线程中的tquery操作
constructor Create(cs: Boolean;tq:Tquery);
overload;
//or
constructor Create(cs: Boolean;tb:Ttable);
overload;
 
多人接受答案了。
 
后退
顶部