我在使用 FireDAC 和 SQLite 的 Delphi 应用程序中遇到间歇性错误,专门在 Delphi 10 Seattle 中配置。
这个问题特别令人困惑,因为它只发生在一个特定的客户身上,表现出看似不确定的行为。通常,系统在重新启动后会恢复正常功能,但随后问题会意外地再次出现。我们无法在内部重现这些错误。它们只能通过使用 EurekaLog 来识别。
TFDConnection的配置:
两个进程同时访问数据库:通常,一个进程写入,另一个进程读取。没有繁重的负载,并且非常罕见的并发写入尝试可以通过锁等待设置有效管理。
此处显示的示例仅适用于读取操作。
目标: 使用带有一个变量的准备好的语句来获取 SOP 实例 UID 的排序列表。
Query := FQuerySortImagesByInstanceNoAsc;
try
begin
Query.ParamByName('series_iuid').Value := SeriesInstanceUID;
Query.Open;
while not Query.Eof do
begin
SopInstUIDs.Add(Query.FieldByName(...).AsString);
Query.Next;
end;
end;
finally
Query.Close;
end;
失败于
Query.Next
。
ExceptionClass: EFDException
ExceptionMessage: [FireDAC][Phys][SQLITE]-311. Command must be open for fetching.
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|Methods |Details|Stack |Address |Module |Offset |Unit |Class |Procedure/Method |Line |
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|*Exception Thread: ID=136748; Parent=131140; Priority=0 |
|Class=TQueryThread; Name=[Unnamed thread] Kind: TThread. Thread function: ...
|DeadLock=0; Wait Chain= |
|Comment= |
|--------------------------------------------------------------------------------------------------------------------------------------------------------------|
|7FFFFFFE|04 |0000000000000000|0000000000EC87A7|App.exe |0000000000AC87A7|FireDAC.Stan.Error | |FDException |189[27] |
|00000020|04 |000000000D27EF68|000000000107C1B1|App.exe |0000000000C7C1B1|FireDAC.Phys |TFDPhysCommand |FetchBase |8661[17] |
|00000020|04 |000000000D27F018|000000000107B804|App.exe |0000000000C7B804|FireDAC.Phys |TFDPhysCommandAsyncFetch|Execute |8540[1] |
|00000020|04 |000000000D27F048|00000000010AAACA|App.exe |0000000000CAAACA|FireDAC.Stan.Async |TFDStanAsyncExecutor |ExecuteOperation |175[6] |
|00000020|04 |000000000D27F0A8|00000000010AAFE5|App.exe |0000000000CAAFE5|FireDAC.Stan.Async |TFDStanAsyncExecutor |Run |270[12] |
|00000020|04 |000000000D27F158|0000000001070964|App.exe |0000000000C70964|FireDAC.Phys |TFDPhysCommand |ExecuteTask |6575[21] |
|00000020|04 |000000000D27F1E8|000000000107C919|App.exe |0000000000C7C919|FireDAC.Phys |TFDPhysCommand |Fetch |8751[2] |
|00000020|04 |000000000D27F268|00000000010F302E|App.exe |0000000000CF302E|FireDAC.Comp.Client |TFDCustomCommand |Fetch |7032[11] |
|00000020|04 |000000000D27F388|00000000010F54A7|App.exe |0000000000CF54A7|FireDAC.Comp.Client |TFDCustomTableAdapter |Fetch |7801[3] |
|00000020|04 |000000000D27F3C8|00000000010FAB3E|App.exe |0000000000CFAB3E|FireDAC.Comp.Client |TFDAdaptedDataSet |DoFetch |9957[3] |
|00000020|04 |000000000D27F408|00000000010C1CB2|App.exe |0000000000CC1CB2|FireDAC.Comp.DataSet|TFDDataSet |InternalFetchRows |4485[25] |
|00000020|04 |000000000D27F488|00000000010BF0C5|App.exe |0000000000CBF0C5|FireDAC.Comp.DataSet|TFDDataSet |GetRecord |3551[16] |
|00000020|04 |000000000D27F4D8|0000000000EBA653|App.exe |0000000000ABA653|Data.DB |TDataSet |GetNextRecord |13812[9] |
|00000020|04 |000000000D27F518|0000000000EBB272|App.exe |0000000000ABB272|Data.DB |TDataSet |MoveBy |14183[16] |
|00000020|04 |000000000D27F578|0000000000EBB4CE|App.exe |0000000000ABB4CE|Data.DB |TDataSet |Next |14227[3] |
|00000020|04 |000000000D27F5A8|0000000001242159|App.exe |0000000000E42159|SQLiteConnection |TSQLiteConnection |SortImagesBySortType|577[26] |
|--------------------------------------------------------------------------------------------------------------------------------------------------------------|
目标: 使用带有一个变量的准备好的语句确定属于当前系列的文件数。
Query := FQueryGetFileCountSeries;
try
Query.ParamByName('series_iuid').Value := SeriesInstanceUID;
Query.Open;
Result := Query.Fields[0].AsInteger;
finally
Query.Close;
end;
失败于
Query.Close
。
ExceptionClass: EInvalidPointer
ExceptionMessage: Application made attempt to free invalid or unknown memory block: $000000000F6B02B0 DATA [?] 0 bytes.
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|Methods |Details|Stack |Address |Module |Offset |Unit |Class |Procedure/Method |Line |
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|*Exception Thread: ID=139204; Parent=0; Priority=0 |
|Class=; Name=MAIN |
|DeadLock=0; Wait Chain= |
|Comment= |
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|7FFFFFFE|04 |0000000000000000|0000000000412285|App.exe |0000000000012285|System | |_UStrClr |24641[8] |
|00000020|04 |000000000014DC38|0000000000412342|App.exe |0000000000012342|System | |_UStrArrayClr |24786[4] |
|00000020|04 |000000000014DC78|00000000004150DA|App.exe |00000000000150DA|System | |_FinalizeArray |31726[24] |
|00000020|04 |000000000014DCC8|0000000000414FE0|App.exe |0000000000014FE0|System | |_FinalizeRecord |31577[18] |
|00000020|04 |000000000014DD18|000000000040EF1E|App.exe |000000000000EF1E|System |TObject |CleanupInstance |16368[8] |
|00000020|04 |000000000014DD58|000000000040ED3B|App.exe |000000000000ED3B|System |TObject |FreeInstance |16186[1] |
|00000020|04 |000000000014DD88|000000000040F82E|App.exe |000000000000F82E|System | |_ClassDestroy |17536[1] |
|00000020|04 |000000000014DDB8|0000000000E9D8F8|App.exe |0000000000A9D8F8|Data.DB |TField |Destroy |4809[9] |
|00000020|04 |000000000014DDF8|000000000040EE65|App.exe |000000000000EE65|System |TObject |Free |16255[5] |
|00000020|04 |000000000014DE28|0000000000E9CB6A|App.exe |0000000000A9CB6A|Data.DB |TFields |ClearBase |4487[14] |
|00000020|04 |000000000014DE88|0000000000E9CC46|App.exe |0000000000A9CC46|Data.DB |TFields |ClearAutomatic |4506[1] |
|00000020|04 |000000000014DEB8|0000000000EB717E|App.exe |0000000000AB717E|Data.DB |TDataSet |DestroyFields |12782[1] |
|00000020|04 |000000000014DEF8|00000000010BD795|App.exe |0000000000CBD795|FireDAC.Comp.DataSet|TFDDataSet |InternalClose |3068[21] |
|00000020|04 |000000000014DF78|00000000010F9C93|App.exe |0000000000CF9C93|FireDAC.Comp.Client |TFDAdaptedDataSet |InternalClose |9628[2] |
|00000020|04 |000000000014DFA8|00000000010FD3BD|App.exe |0000000000CFD3BD|FireDAC.Comp.Client |TFDRdbmsDataSet |InternalClose |11018[3] |
|00000020|04 |000000000014DFF8|0000000000EB631C|App.exe |0000000000AB631C|Data.DB |TDataSet |CloseCursor |12528[6] |
|00000020|04 |000000000014E038|00000000010BD03E|App.exe |0000000000CBD03E|FireDAC.Comp.DataSet|TFDDataSet |CloseCursor |2939[3] |
|00000020|04 |000000000014E078|0000000000EB60BA|App.exe |0000000000AB60BA|Data.DB |TDataSet |SetActive |12480[22] |
|00000020|04 |000000000014E0C8|00000000010B881C|App.exe |0000000000CB881C|FireDAC.Comp.DataSet|TFDDataSet |SetActive |1581[7] |
|00000020|04 |000000000014E0F8|0000000000EB5DB1|App.exe |0000000000AB5DB1|Data.DB |TDataSet |Close |12431[1] |
|00000020|04 |000000000014E128|000000000124D247|App.exe |0000000000E4D247|SQLiteConnection |TSQLiteConnection |GetFileCountSeries |1582[8] |
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
我使用
TThread.Synchronize
将相关调用移至主线程,这解决了问题。