I probably misundertood something about SAVEPOINTS in SQLite.
I am using C API in an application, where we run a bunch of inserts, and in case something fails, we should give up on all the inserts alltogether.
I am aware I could BEGIN TRANSACTION for such a simple scenario, but I fear that the scenario could get a more complicated, and nesting might become a requirement, that's why I went for SAVEPOINTS.
Anyway, here is an extract of SQL statements I run:
SQL> SAVEPOINT SAVEPOINT_20170524_172706;
SQL> INSERT, SELECT STATEMENT (no COMMIT or END TRANSACTION)
SQL> ROLLBACK TO SAVEPOINT SAVEPOINT_20170524_172706;
SQL> RELEASE SAVEPOINT_20170524_172706;
Basically I create a new savepoint based on the timestamp, before I start inserting and selecting data from the database.
Then one operation fails and I need to bail out, so I rollback to the savepoint I just created.
In the end I want to get rid of the savepoint I wont need anymore, since I dont want to clutter the database with useless savepoints, hence I ran RELEASE . In this case I find myself with the database filled with all the data inserted by statements that were supposed to be rolled back.
If I dont execute the RELEASE statement, then the database looks just fine, but I wonder what happens with the abandoned SAVEPOINT which will never be referenced anymore.
Which wrong assumption am I making? What happens to SAVEPOINTS if I dont release them, are they going to be 'dropped' as I close the 'connection' to the DB file?
I had PRAGMA journal_mode = OFF
Related
I'm using python3.6 and pymysql 0.7.11.
The call to rollback rolls a transaction back, according to the documentation.
A call to commit finalises a transaction.
My question is whether after a call to rollback it is prudent to call commit ... ?
this is not really a python question but about mysql transactions.
you can read about it at http://www.mysqltutorial.org/mysql-transaction.aspx for example.
in short: you need to start a transaction to rollback or commit it.
usually autocommit is enabled if you don't want to use transactions manually .. in that case mysql creates a transaction for every statement.
I've been reading a lot lately and I am now very confused how transactions and locking are working and how are related to each other.
When working with SQLite, imagine the following flow:
begin SQLite transaction
run a select statement on a SQLite connection to return values
if condition is met on the returned values, go to step #4, otherwise go to step #5
do the update
commit SQLite transaction
If two threads run same code, is there a possibility that in one of the threads could get what is called a "dirty read" meaning, between the step #3 and step #4, the other thread could run the update (step #4)?
Yes, it's called isolation level: https://www.sqlite.org/isolation.html
I am trying to understand Savepoints and Transactions in SQLite.
I had the following commands on a Table/Database and I am using Savepoints.
SAVEPOINT aaa;
RELEASE aaa;
BEGIN;
Now, if I execute all the above statements at once, its throwing an error saying that A transaction cannot be started inside another transaction. If I run them one at a time, it works fine.
if I run the first two Savepoint and release commands and try to start another transaction by executing the Begin. it again throws the same error as previous.
The link here says that
If the SAVEPOINT command is issued when SQLite is in autocommit mode—that is, outside of a transaction—then a standard autocommit BEGIN DEFERRED TRANSACTION will be started. However, unlike with most commands, the autocommit transaction will not automatically commit after the SAVEPOINT command returns, leaving the system inside an open transaction. The automatic transaction will remain active until the original save-point is released, or the outer transaction is either explicitly committed or rolled back. `
So, Is it absolutely necessary for a Commit or Rollback command after the Release Savepoint Command? Doesn't release command commit and allow us to start a new transaction using BEGIN?
SAVEPOINT aaa;
RELEASE aaa;
BEGIN;
is interpreted by sqlite as
BEGIN DEFERRED TRANSACTION; SAVEPOINT aaa; // Create a transaction, and mark current db state as savepoint "aaa" [1]
RELEASE aaa; // Remove all db changes made since savepoint "aaa", but keep on executing the transaction
BEGIN; // Create another transaction, while there is already a transaction. This will FAIL because there cannot be 2 transactions executed simultaneously
The following would be fine:
BEGIN;
SAVEPOINT "aaa";
RELEASE "aaa";
COMMIT;
BEGIN;
[1] https://sqlite.org/lang_savepoint.html
I have a process that is steadily inserting into a sqlite db, using hibernate.
Everything works fine if I leave it alone.
If however, I start a sqlite3 session to the db file and run a query, I immediately get a "sqlite LOCKED" exception in my inserting process.
First off, this is contrary to sqlite docs, which says LOCKED is only internal.
In any case, once I get the error, I catch the exception and move on the next insert.
And I close my external sqlite session.
But going forward, when I try to commit, it hangs for a long time, many minutes - and then I finally get
Caused by: java.sql.SQLException: SQL logic error or missing database
The sqlite db is still very much there.
Why would I get this error?
Also, any way I can get rid of the LOCKED error - I dont have this issue with other databases when I have multiple sessions - why only sqlite?
I'm Altering multiple sqlite tables with SQL script by calling ExecuteNonQuery. I want to do this operation in transaction and want to roll it back when anything fails.
I looked at BEGIN TRANSACTION and its clear that I have to call ROLLBACK TRANSACTION when anything goes wrong. But I don't know how could TRY...CATCH (Transact-SQL) kind of thing here.
NOTE: Whole of Sql Script file (which contains many other statements apart from these few statements which needs to be fired in one transaction) is read by .ReadToEnd() and then executed in one go as of now. I want to handle this in sql script file itself and don't want to change the code.
Please take a look at SQLite on conflict clause
Start with BEGIN TRANSACTION
You have to add ON CONFLICT ROLLBACK on your actions
And COMMIT TRANSACTION at the end ;-)