[Lazarus] SQLdb: Pseudo Transaction?

R.Smith ryansmithhe at gmail.com
Tue Jun 30 01:55:37 CEST 2020

Hi Joe,

I'm hardly a FPC/SQLdb expert, but I am somewhat familiar with SQL 
databases and SQLite in particular.

Your problem is exactly what is expected.

Basically you are trying to execute SQL code in SQLite that changes the 
underlying DB engine to change the journalling mode (or at least, a 
component of it, namely "synchronous") while you have already started a 
transaction "XConnection.Transaction:= XTransaction;".

Now in SQLite, since it is a file-based DB engine, it needs to be able 
to lock files (with standard OS file-locking semantics) during 
reading/writing as needed. It is able to provide full ACID transactions 
by using "Journals" of various types that funtion in various ways. The 
best is to use WAL journal mode, but the fastest would be DELETE mode, 
etc.  It aslo has the "synchronous" pragama switch that controls HOW the 
underlying engine confirms writes to actual hardware via the current VFS 
(virtual file system) in use. [Think of a VFS like a driver for EXT4, 
NTFS, whatever you are using.]

With "PRAGMA synchronous = OFF" you are telling the the VFS to stop 
FSYNCing after writes on your file system. i.e. to not care whether your 
data has been comitted to the physical hardware, but return immediately 
after writing and go on with the next thing. This is a nice hack to make 
it very fast, but it does cause a measure of risk for a power-cut right 
at the point between sending the write, and accepting it is completed 
when it really isn't comitted to hardware, will mean data corruption 
(detected when you next start up).

This is called "SAFETY LEVEL" and for obvious reasons, you cannot change 
how the safety mechanism acts while already inside a transaction which 
started on a certain safety level. You have to perform this swicth 
BEFORE starting that transaction.

Just remove all the transaction bits of your code, and it should work fine.

By the way, if you don't care about safety at all, also make sure the 
"PRAGMA journal_mode = DELETE;"[1] is called (also before any 
transaction), set the temp-store to memory[2] and set the cache nice and 
[1] https://sqlite.org/pragma.html#pragma_journal_mode
[2] https://sqlite.org/pragma.html#pragma_temp_store
[3] https://sqlite.org/pragma.html#pragma_cache_size

(and if you do care about data safety, don't do any of those!)

(except the cache... you can still do the cache.) :)


On 2020/06/30 00:25, Special via lazarus wrote:
> Hi,
> I am  using Lazarus 2.0.8, package SQLdb, under Win 10  (64). The 
> following procedure raises an exception with message 
> "TSQLite3Connection: Safety level may not be changed inside a 
> transaction". This is strange, since I think there is no active 
> transition in the moment when the exeption is raised.
> Why this exception? How to fix? Is it maybe a bug in Lazarus 2.0.8 or 
> in SQLdb?
> Code:
> procedure TForm1.TestButtonClick(Sender: TObject);
> var XConnection:   TSQLite3Connection;
>     XTransaction:  TSQLTransaction;
>     XDatasource:   TDataSource;
>     XQuery:        TSQLQuery;
> begin
>   XConnection:= TSQLite3Connection.Create(Form1);
>   XTransaction:= TSQLTransaction.Create(Form1);
>   XDatasource:= TDataSource.Create(Form1);
>   XQuery:= TSQLQuery.Create(Form1);
>   XQuery.DataBase:= XConnection;
>   XQuery.Transaction:= XTransaction;
>   XDatasource.DataSet:= XQuery;
>   XTransaction.DataBase:= XConnection;
>   XConnection.Transaction:= XTransaction;
>   XConnection.DatabaseName:= ExtractFilePath (Application.ExeName) + 
> 'D.sqlite';
>   XQuery.SQL.Text:= 'PRAGMA synchronous=OFF';
>   try
>     XQuery.ExecSQL;
>     XTransaction.Commit;
>   except
>     on e: Exception do
>     ShowMessage ('Exception "' + e.Message + '"')
>   end;
>   XQuery.Free;
>   XDatasource.Free;
>   XTransaction.Free;
>   XConnection.Free;
> end;
> Regards --  Joe
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus-ide.org/pipermail/lazarus/attachments/20200630/ae271143/attachment-0001.html>

More information about the lazarus mailing list