300分的数据库并行操作问题.欢迎有能力高手做答....(300分)

  • 主题发起人 主题发起人 lonelyboy
  • 开始时间 开始时间
L

lonelyboy

Unregistered / Unconfirmed
GUEST, unregistred user!
在一个多人操作的系统(sql server 7.0)中做一个操作如下:
对两个表做eidt,对另外一个表做insert,然后一起保存.该操作经常会有多个人一起
保存.程序语句大致如下:
代码:
query1.edit;
...
query1.post;
query2.edit;
....
query2.post;
query3.insert;
...
query3.post;
database1.StartTransaction;
  try
    query1.ApplyUpdates;
    query2.ApplyUpdates;
    query3.ApplyUpdates;
    database1.Commit;
  except
     database1.Rollback;
     showmessage('冲销发生错误,已经恢复,请退出冲销程序再做一次,谢谢');
  end;
 query1.CommitUpdates;
 query2.CommitUpdates;
 query3.CommitUpdates;
现在程序时常会出现以下语句:
General SQL error.
[Microsolf][odbc sql server driver][sql error]
your transaction(process ID #21) was deadlocked with another process and has
been closen as the deadlock victim. Return your transaction.
确定以后,系统经常会有以下出错现象
表A已经保存,但表b和c就还没有保存.使最后结果出现错误.
这种出错是出现在多人操作的时候,我自己一台机器操作的时候就没有出现过这种出错语句
这个问题我已经思考了很久,但是还是没有想到我到底是错在那里,我很苦恼啊(领导对我的压力)
请各位高手程序员帮帮我.因为一出错就要手工修改,工作量实在是太大了.真心请各位
高手帮帮我。程序是用delphi5.0写的,使用了inforpower3000控件.
大恩不忘报啊!!!!
 
用delphi自帶的數據庫吧
paratox,沒有看到過可以破解它的工具
 
對不起﹐回答錯了﹗﹗﹗也想過這樣的問題!我是這樣想的﹐不知道有不有用﹐在每條記錄
上加個標志,新增記錄應該是沒有問題的﹗修改與刪除就要注意﹕
當第一個人在用這條記錄時﹐把它的標志標為,'在用'﹐此時﹐其它的用戶只能看﹐不能
刪除與修改,當此條記錄不用的時候﹐把它的標志標為,'可用'.
也就是說當此記錄為'在用'時﹐其它用戶只能看﹐當此條記錄為'可用'時﹐你讀取此記錄時
把它標為'在用',此時你就可以對它修改與刪除了﹗﹗
以上為小弟之愚見﹗不要笑話!!
 
通过提供数据的形式,把规则设计成存储过程,让SQLserver自己安排估计就不会或者会很少出现这样的问题了。
 
象你这样对数据库操作的需求,最好是使用存储过程来实现!
想在客户端控制这样的并发机制,那可不是一件很容易的事。
整个一次的对数据库的修改工作,封装到一个存储过程中,这样应该不会出现问题。
 
Specifies the transaction isolation level for transactions managed by the Borland Database Engine (BDE).

type TTransIsolation = (tiDirtyRead, tiReadCommitted, tiRepeatableRead);
property TransIsolation: TTransIsolation;

Description

Use TransIsolation to specify the transaction isolation level for database transactions managed by the BDE. Transaction isolation level determines how a transaction interacts with other simultaneous transactions when they work with the same tables, and how much a transaction sees of the work performed by other transactions.

Note: Applications that use passthrough SQL for handling transactions must pass a transaction isolation level directly to the database server using the appropriate SQL statement.

TransIsolation can be any one of the three values summarized in the following table:

Isolation level Meaning

tiDirtyRead Permits reading of uncommitted changes made to the database by other simultaneous transactions. Uncommitted changes are not permanent, and might be rolled back (undone) at any time. At this level a transaction is least isolated from the effects of other transactions.
tiReadCommitted Permits reading of committed (permanent) changes made to the database by other simultaneous transactions. This is the default TransIsolation property value.
tiRepeatableRead Permits a single, one-time reading of the database. The transaction cannot see any subsequent changes made by other simultaneous transactions. This isolation level guarantees that once a transaction reads a record, its view of that record does not change unless it makes a modification to the record itself. At this level, a transaction is most isolated from other transactions.

Different database servers support different levels of transaction isolation. If an application sets TransIsolation to an unsupported level for a remote SQL server, the BDE uses the next highest level supported by that server. The following table summarizes the isolation levels supported by the servers recognized by the BDE:

Server Specified Level Actual Level
Oracle tiDirtyReadtiReadCommittedtiRepeatableRead tiReadCommittedtiReadCommittedtiRepeatableRead (READONLY)
Sybase, MS-SQL tiDirtyReadtiReadCommittedtiRepeatableRead tiReadCommittedtiReadCommittedNot supported
DB2 tiDirtyReadtiReadCommittedtiRepeatableRead tiDirtyReadtiReadCommittedtiRepeatableRead
Informix tiDirtyReadtiReadCommittedtiRepeatableRead tiDirtyReadtiReadCommittedtiRepeatableRead
InterBase tiDirtyReadtiReadCommittedtiRepeatableRead tiReadCommittedtiReadCommittedtiRepeatableRead
Paradox, dBASE, Access, FoxPro tiDirtyReadtiReadCommittedtiRepeatableRead tiDirtyReadNot supportedNot supported
Note: For local transactions against Paradox and dBASE, TransIsolation must be set to tiDirtyRead. Otherwise, an exception is raised.

If an application uses ODBC to interface with a server, the ODBC driver must also support the isolation level. For more information about supported isolation levels, see the documentation for the ODBC driver in question.
不知道具体怎么做能满足你的要求,
但是这是一个方法
 
先了解数据完整性的要求,用动态生成的sql语句更新数据库有更好的可控性。
 
我也想过是否可以使用存储过程.但是实在是很难实现的.
我现在就是想知道怎么克服死锁的问题.
为什么它会一个表修改,而另外两个表没有修改呢?
我把
query1.ApplyUpdates;
query2.ApplyUpdates;
query3.ApplyUpdates;
database1.Commit;
改为database1.ApplyUpdates([query1,query2,query3]);
是否不会出现一个表修改,另外两个表不修改的情况?
 
database1.TransIsolation:=tiRepeatableRead
试一试
 
1.尽量使用存储过程,应该可以实现的.
比如 update语句就把主键和要修改的列的值当参数传给存储过程,delete语句只传主键就行了.
2.必要时把页级锁改成行级锁.
3.在query的sql语句后加 noholdlock,不过这样不能防止 dirty read.
总之尽量使锁定资源最小,时间最短。
 
1、使用存储过程。
2、关闭数据库服务器的自动提交功能。
3、考虑是否可以使用触发器。
4、改良你的程序,看的出来你的设计工作没做到位!
 
对,用存储过程+行级锁
 
[:(]各位高手都说是使用存储过程.但是我的程序是
在query1循环完毕之后才一起ApplyUpdates的
不只是对一条记录做操作的.这样一来用存储过程
可以吗?
请教一下有谁可以给我写一个简单的存储过程例子
让我可以能够学习你们的经验,谢谢[:)]
 
你的QUERY1、QUERY2、QUERY3的CACHEDUPDATES是否开启了?既然是多用户有可能同时对数据
进行操作,就不应该直接对表进行修改或者添加数据。我觉得用UPDATE_SQL和INSERT_SQL比较
合适,比如:
database1.StartTransaction;
try
query1.execsql;
query2.execsql;
query3.execsql;
database1.Commit;
except
database1.Rollback;
showmessage('冲销发生错误,已经恢复,请退出冲销程序再做一次,谢谢');
end;
database1.CommitUpdates;
 
同意::xf-wangyi
 
其实也就是一个并发加锁的问题,在查询时加上for update的行级锁,
这样其他用户必须等待该事务提交或回滚时才能操作数据库,只要
不出现死锁,就没有问题。
我不知道sql server的行级锁机制如何,但在oralce中这是非常简单的事情。
 
在sql server中有是有这种锁的机制,但没有在ORACLE中的方便,只是针对于事务处理
分几个级别使用如
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
 
用ado絕對沒有這樣的問題,
我勸你用ADo了,方便又強大
 
后退
顶部