我曾经问过一次,但却觉得答案不太理想,所以重新抛砖引玉。
我的客户端Delphi录入、查询都是用SQL语句,几乎都是一个格式,
无论增加删除修改我都是只用Tquery控件,而且几乎一律是这样在
按钮中写的:
Query1.close;
query1.sql.text:=‘insert into table1(...) values(...)‘;
query1.execsql;(or open)
只是在text更换不同的语句。‘select * from ...‘,‘delete ...‘
‘update ...‘
有时候我用两台机器特意试的时候,还没什么事,但我们公司长期运行
着我的类似程序,有时却会一台机器毫无反应,有时必须其它机器必须退
出,毫无反应的那台机器起它程序还没事,一回Delphi界面什么也做不了。
我想问问各位你们在多台机器同时向SQL server录入的时候一般的详细
编程语句,不出问题的编程过程。
来自:delphi fan2, 时间:1999-1-25 9:31:00, ID:99075
如果数据批量输入,加入事务处理!要是全部是Insert是否有你说的问题?
来自:dsp, 时间:1999-1-25 19:13:00, ID:99113
您用到了事务吗?
如果没有,不会出现您的问题.
如果用到了,则极有可能是您的两个程序出现了死锁.
因为,在一个事物内UpDate,Insert,Delete会隐式加锁,直到事务结束.
如果您的一个程序为:
StartTransaction;
query1.close;
query1.clear;
query1.sql.add(‘Insert table1....‘);
query1.execsql;
query1.close;
query1.clear;
query1.sql.add(‘Update table2...‘);
query1.execsql;
query1.Close;
commit;
另一个为:
StartTransaction;
query2.close;
query2.clear;
query2.sql.add(‘Insert table2....‘);
query2.execsql;
query2.close;
query2.clear;
query2.sql.add(‘Update table1...‘);
query2.execsql;
query2.Close;
commit;
当第一个执行到语句Update table2,
而第二个执行到语句Update table1时,
会出现相互等待的现象.
解决的办法就是将可能出现冲突的语句全放到事务中执行,而无论哪一个
此类事务均在开始处,对同一个表加锁.这样在事务开始便进行了排队,
直到一个事务结束,另一个才会开始,便不会死锁.
如:
StartTransaction;
query1.close;
query1.clear;
query1.sql.add(‘Select * from commonTable HOLDLOCK‘);
//对SQL Server,不同的database server不同.
query1.Open;
query1.close;
query1.clear;
query1.sql.add(‘Insert table1....‘);
query1.execsql;
query1.close;
query1.clear;
query1.sql.add(‘Update table2...‘);
query1.execsql;
query1.Close;
commit;
StartTransaction;
query2.close;
query2.clear;
query2.sql.add(‘Select * from commonTable HOLDLOCK‘);
query2.Open;
query2.close;
query2.clear;
query2.sql.add(‘Insert table2....‘);
query2.execsql;
query2.close;
query2.clear;
query2.sql.add(‘Update table1...‘);
query2.execsql;
query2.Close;
commit;
这样,二者在select上便进行排队,便解决了排序.
如您根本就没有组织过事务,出现该现象就有点怪了.
来自:希臣, 时间:1999-1-26 8:27:00, ID:99152
dsp,你说的我有点迷糊了。
到底用不用事务?我一点都没有过事务,
按你说的,不用事务,好象是不应该出现问题--是这个意思吗?
Delphi fan2,我的语句Insert,delete ,update,select都有。
两位,如果其它机器只用Select,而一台机器(名A)上
Insert,delete,update,select都用,这机器A会不会和其它机器互锁
来自:dubhe, 时间:1999-1-26 9:29:00, ID:99154
dsp:
insert和update时数据库只对当前操作的记录加锁,而不是对整个表加锁.因此,你
所举的死锁例子不会出现死锁现象.
希臣:
其它机器Select,而A机器Insert,delete,Update,Select都用时,机器A更不会与其
它机器互锁.
一个死锁的例子:
进程A (修改记录1)------->(修改记录2)
进程B (修改记录2)------->(修改记录1)
另外,建议希臣TQuery的写法:
Query1.Close;
Query1.SQL.Clear;
Query1.SQL.Add:=‘Select ... From table1 Where ...‘;
Query1.Open;
... ...
Query1.Close;//不需要时马上Close掉
来自:delphi fan2, 时间:1999-1-26 10:04:00, ID:99156
其实数据库都有事务处理,无论你使不使,数据库自己会使用,所以
你大量输入数据时要显式使用可以提高效率和避免死锁,当一个用户插入,
而另一个用户select是容易出问题,在数据库理论上用事务的处理级别来避免!
不过Sybase支持几个我不知道,在数据库产品里oracle是支持最好的!其他
产品都无法使事务完全独立!
来自:yaojiaqing, 时间:1999-1-27 0:05:00, ID:99179
您看这样行吗?
1,客户段绝对不使用数据感知控件,在客户端录入完成后,使用一个
事物处理将数据传之服务器端。
2,如果客户端使用数据感知控件,在本地用临时表,完成录入后,
在将数据上传,
以上两种方法,都会缩短传输时间。这样网络冲突会很少。
3,对于多表更新或修改,多用触发器或存储过程。
来自:delphi fan2, 时间:1999-1-27 0:13:00, ID:99180
我做数据库程序时从不用数据感知控件,而且输入后不要马上refresh,
因为refresh是很费时的,可以让用户手动刷新!效果不错!
来自:yaojiaqing, 时间:1999-1-27 0:18:00, ID:99181
再补充两点:
1,事物处理要用,数据的完整性嘛。
2,前端的录入界面中,在录入时保证不占用网络。(所以说:要用非数据
感知控件)
来自:xyw, 时间:1999-1-27 20:11:00, ID:99217
一定要采用事务处理;
对服务器端要妥善管理;
来自:蓉儿, 时间:1999-2-3 21:42:00, ID:99874
你的select语句打开后什么时候关闭的?
其实很多时候锁的造成是由于select而不是insert或update,控制好你取数据的机制就可避免很多锁,这点我是有成功的经验.
Delphi的取数据机制是select结果集如果未载入完毕(这种情况很多,如DBGrid一次载入只能1000笔,除非你走动当前记录,它才会继续载入又一部分),则会在后台数据库加一个共享锁,SQLServer蠢在如果这个共享锁有就不能update或insert相应页面数据(该共享锁锁的是未载数据页面),感觉这种低级问题应该不会有但是确实存在.
我的实践证明MSSQLServer不是一个很稳定的数据库,除非你不乱动,则一般不会出错.或者说用Delphi的数据库控件(或者说是BDE)去访问SQLServer不是很精炼.
不过也不是根本行不通,设计合理还是可以的
建议你:
1.Client端select语句尽量精简
2.select取完数据则关闭连接
3.数据库控件特别是DBGrid尽量少用,宁肯自己多花一点时间写界面,其实自己控制一切速度绝对比它们快得多
4.insert.update语句设计合理,能用Trigger尽量用Trigger
来自:lzl, 时间:1999-2-3 23:41:00, ID:99894
前面各位说的都很对, 不过有时是无法避免这类问题的, 原因出在数据库
的页级锁和表级锁, 例如在SQL Server 6.5:
1.
begin transaction
insert into delegateinfdetail
values (54,‘23‘,‘43‘,‘1‘,‘1‘,132.00)
waitfor delay "00:00:10"
commit
2. select * from delegateinfdetail
同时开两个用户窗口分别同时执行这两段SQL, 2会等待直至1完成事务提交
可能这是sql server的问题, 不知道其它怎么样.
所以
1. 尽量避免使用数据感知控件
2. 减少事务处理时间
3. 尽可能使用多线程处理查询, 避免用户端等待 (关于多线程查询应该有例子, 不然
mail 我)
来自:taik, 时间:1999-2-4 20:18:00, ID:99951
1.先吃个Sybase补丁,EBFxxxx.exe等,Sybase主页上有,很难找。
2.BDE设置CS Cursors Rows=100~200(BDE 5.01才有)。
3.你Sybase版本?
4.如果不会多人同时输入同一条记录的话有其他办法。
5.上面有些提法不对,Sybase最新的版本才有Row级锁,旧的
是Page锁。
6.要用显式的事务控制,在提交出错时要再尝试或Rollback.
7.开发环境接近,好好切磋下。
来自:xhm, 时间:1999-2-12 7:18:00, ID:100882
没有提交,引起死锁!
来自:唐晓锋, 时间:1999-2-26 18:14:00, ID:101305
你用线程不行吗?
来自:mindong, 时间:1999-3-31 1:46:00, ID:103523
线程可以解决。
来自:tangyin, 时间:1999-4-9 22:40:00, ID:104834
我最近也碰到类似的问题。在Delphi客户端用query来SELECT一个表,居然导致
其他用户insert,update等出现阻塞。但不用数据感知控件似乎不太现实。如果
是蓉儿所说的情况,希望能有较完善的解决方案。
一是SQL server端能否做些设置,或Delphi端有什么办法释放锁。
来自:silly, 时间:1999-4-19 19:51:00, ID:105847
Delphi连接SYSBASE11时,BDE的配置使用DB-LIBERARY就不会造成死琐,特别针对SELECT死锁现象。
来自:tai, 时间:1999-4-20 12:02:00, ID:105872
DB-Liberary是被淘汰的,不建议用,为了兼容才留了这东东。
来自:tangyin, 时间:1999-4-20 12:35:00, ID:105874
不用DB-Liberary你说用什么呢?
来自:xhm, 时间:1999-4-20 12:54:00, ID:105877
CT-Library
来自:tangyin, 时间:1999-4-20 17:50:00, ID:105922
如何配置CT-LIBRARY?
来自:silly, 时间:1999-4-22 23:20:00, ID:106317
WhyNotDBLibrary?TechnicalReasonsPls.
来自:SeaSky, 时间:1999-4-23 0:07:00, ID:106321
你试试 在Select 语句中加上 NoHoldLock选项, 例如
select * from Tabl1 A NoHoldLock
where .....
来自:jun_yan, 时间:1999-4-23 11:21:00, ID:106350
1。TQuery我用的不多,但在使用 TTable 控件时,常常遇到类似的死锁现象:
Can‘t perform this on table ,for record has been modified by
other users!
即使用DATA EXPLORER<