有两个工作线程A和B,在程序运行期间,每接收到一次数据请求,就调用函数ExecuteQuery,往同一个数据库表ws_source里写数据。任一个线程调用ExecuteQuery时,都会动态创建一个临时的TADOConnection对象,执行SQL完毕之后,再将它释放。
/// <summary>
/// 执行返回受影响的行数
/// </summary>
function ExecuteNoQuery(ACommandText:string):Integer;var
Query: TADOQuery;
ADOConnection : TADOConnection;
begin
ADOConnection := GetConnection();
try
Query := TADOQuery.Create(Application); // 问题:数据高峰时,会发生创建失败
try
With Query do
begin
Connection := ADOConnection;
Close;
SQL.Clear;
SQL.Add(ACommandText);
try
Result := ExecSQL;
except
on E:EOleException do
begin
// 如失去连接则重新连接
if (CompareText(E.Message,'Connection failure')=0) or
(CompareText(E.Message,'连接失败')=0) then
begin
ADOConnection.Connected := False;
ADOConnection.Connected := True;
Result := ExecSQL;
end
else
begin
raise;
end;
end
else
begin
raise;
end;
end;
end;
finally
Query.Free;
end;
finally
ReleaseConnection(ADOConnection);
end;
end;
现在的问题是,一般在每天的早上9点~10点会有一次数据高峰期,这时就会频繁发生TADOQuery创建失败的情况,导致数据无法写入数据库。
/// <summary>
/// 执行返回受影响的行数
/// </summary>
function ExecuteNoQuery(ACommandText:string):Integer;var
Query: TADOQuery;
ADOConnection : TADOConnection;
begin
ADOConnection := GetConnection();
try
Query := TADOQuery.Create(Application); // 问题:数据高峰时,会发生创建失败
try
With Query do
begin
Connection := ADOConnection;
Close;
SQL.Clear;
SQL.Add(ACommandText);
try
Result := ExecSQL;
except
on E:EOleException do
begin
// 如失去连接则重新连接
if (CompareText(E.Message,'Connection failure')=0) or
(CompareText(E.Message,'连接失败')=0) then
begin
ADOConnection.Connected := False;
ADOConnection.Connected := True;
Result := ExecSQL;
end
else
begin
raise;
end;
end
else
begin
raise;
end;
end;
end;
finally
Query.Free;
end;
finally
ReleaseConnection(ADOConnection);
end;
end;
现在的问题是,一般在每天的早上9点~10点会有一次数据高峰期,这时就会频繁发生TADOQuery创建失败的情况,导致数据无法写入数据库。
因为,程序里还有其他的线程要访问这个数据库的其他表,其他线程会不会因为程序运行期间始终存在一个全局TADOQquery对象,而无法创建另外的TADOQquery对象?
Access violation at address 00490057 in module 'MonitorServer.exe'. Read of address F1751E1D
不知道从这里能看出什么呢?
看到网上这么说(链接地址http://www.myexception.cn/delphi/264643.html):ADOQquery.Free后,由于ADO本身的特性,这个ADOQquery对应的数据库连接要过一段时间才会被释放掉。如果在短时间内大量地创建和释放ADOQquery,就会有大量的数据库连接来不及释放掉,导致后面无法创建ADOQquery。当数据高峰过后,堆积的数据库连接会逐渐被释放掉,所以后面又可以创建ADOQquery了。这个说法,很好解释了我的问题。但如何解决这个问题呢?
多谢两位。
后来把这问题解决了。
频繁地创建和释放是没关系的,主要是“Query := TADOQuery.Create(Application);
”这句有问题,因为创建TADOQuery的对象的Parent是Application,所以当手动释放时,一般要过一段时间才真正被释放。将它改为“Query := TADOQuery.Create(nil);
”,问题就解决了。