A transactional Rollback of a liquibase changeset - liquibase

I am currently using liquibase with SQL based changeset, and most of them contain INSERT statements. According to the documentation this type of update operation does not produce, (by the tool) automatic rollback statements.
My question is (I might be missing something), since we can declare that a certain changeset can run in the context of a DB transaction, if an error occurs during applying the changeset, can the tool (liquibase) just issue a transaction roll back for this specific changeset?
My case is that currently all these scripts are part of a development process and these scripts are not yet final, meaning that someone changes the content, and we reply them from scratch. If in a 2000 line insert script there is a error in the SQL, I would like the tool to automatically rollback the currently transaction and not commit the changes in the DB.
Many thanks for any tips

During the update process, liquibase runs each changeSet in a transaction and rolls it back if there are any errors. So If you have a 2000 line insert with an error half way through it will fail as expected and roll back automatically.
What is not generated automatically is SQL to "roll back" (in this case delete) the inserts after they have been committed. If you specify a block in your changeSet, then after update successfully executes and been committed, you can later on run "liquibase rollback v2.3" and it will undo changes since the v2.3 tag. It cannot rely on the database rollback functionality because it is already committed.
It is probably a bit confusing since rollback in this case is different than the normal database use of the term "rollback" in the context of a transaction.

Related

What happen with modifications queries when JDBC application abnormaly exited or connection dropped (Oracle is this essential)?

I call extensive update SQL statement and PL/SQL procedures.
What will happen with data when my application lose connection to DB or server halted or etc?
In case of SQL update command I think that it will be rollback.
For PL/SQL procedure I assume that code execution stopped at some time, any previous commit command will be applied but rest of code doesn't.
Am I right?
Yes it should rollback to the last rollback/commit call.
This became too long for a comment.
DDL statements (truncate, create, drop,...) implicitly commit. So if you do that in your stored procedure calls, everything before that statement will be committed whether you want or not. If the jdbc session is lost after the truncate, the changes before are still committed.
And yes, if you are inserting large volumes without intermediate commits, things can slow down. This is typically because you are building up rollback segments. There is a sweet spot with large inserts where you insert a batch of, say, 1,000 records at a time, committing after each batch.
What you are describing does not seem like normal transactional activity but more like bulk loading. If you are bulk loading, then maintain state so that you can restart the load or discard the records already loaded if you replay. Consider things like shipping as a file and importing (or using an external table) rather than necessarily inserting via a client connection. The APPEND hint and INSERT's NOLOGGING clause to speed up inserts (but note that the db will not be in a typical 'recoverable' state afterward and should be backed up again).

Do I need to call rollback if I never commit?

I am connecting to a SQL Server using no autocommit. If everything is successful, I call commit. Otherwise, I just exit. Do I need to explicitly call rollback, or will it be rolled back automatically when we close the connection without committing?
In case it matters, I'm executing the SQL commands from within proc sql in SAS.
UPDATE: It looks like SAS may call commit automatically at the end of the proc sql block if rollback is not called. So in this case, rollback would be more than good practice; it would be necessary.
Final Update: We ended up switching to a new system, which seems to me to behave the opposite of our previous one. On ending the transaction without specifying committing or rolling back, it will roll back. So, the advice given below is definitely correct: always explicitly commit or rollback.
It should roll back on close of connection. Emphasis on should for a reason :-)
Proper transaction and error handling should have you always commit when the conditions for commit are met and rollback when they aren't. I think it is a great habit to always commit or rollback when done and not rely on disconnect/etc. All it takes is one mistake or incorrectly/not closed session to create a blocking chain nightmare for all :-)

Can I rollback a SQLite transaction after it has been committed?

Is there a way in SQLite to essentially undo the latest transaction after it has been committed?
I'd like to revert the database to the state before a transaction or savepoint. I've looked at the rollback command, but it looks like it is limited to rolling back a pending transaction.
Edit
Could I create a savepoint named "Undo" and wait to release it before starting the next action, or rollback if I need to undo it?
I am not sure if you are using JDBC 3.0. If you are then it supports savepoints. http://www.ibm.com/developerworks/java/library/j-jdbcnew/
Other than doing an on-line backup prior to your transaction, I don't know that it supports a "time machine" to go backwards in time.
Can't you put some application logic in place to record enough to undo the applied operation in audit trail table(s)?
I'm not an SQLite expert, but as far as I've tried, it's only possible to make savepoints inside transactions, but not the opposite.
And AFAIK, reading the online documentation, savepoints and transactions are essencially the same, the difference is the transaction stack in which the savepoints are written. You could open a certain number of savepoints (remembering the stack ordering) and, after checking it'a OK, make a transaction commit. I don't know if this will help you.

Using TSQLUnit to test INSTEAD OF triggers

I have an INSTEAD OF trigger on a table in my SQL Server 2005 database that checks several incoming values. If an incoming value is invalid, an error is raised and the transaction is rolled back. Otherwise the record is inserted.
I would like to include a TSQLUnit test of this trigger where, if an invalid value is inserted, having the transaction rolled back is the successful outcome of the test. I have created a test procedure to do this, but rolling back the transaction aborts execution of the whole suite of tests.
Has anyone had success with this? If so, how did you accomplish it?
If this is not possible with TSQLUnit, how do you test your triggers? Or do you test them at all?
I don't know if it's TSQLUnit or just standard behavior of SQL you're seeing.
A trigger exception in SQL Server 2000 and earlier is batch aborting on ROLLBACK because ##TRANCOUNT = 0
With TRY/CATCH in SQL Server 2005 the behavior changes and the client should handle it correctly. Saying that, I'd wrap the outer call in TRY/CATCH too anyway.
Suggestions:
check the state of data before and after to see what you have
use a stored procedure (which is what you're doing anyway)
use TRY/CATCH
There is another TSQL unit testing framework called TST http://tst.codeplex.com/ that supposedly allows testing code that has its own transactions. From the TST docs:
"When the tested code has its own transactions, TST uses a reliable way of detecting the cases where its own rollback mechanism becomes ineffective. The TST rollback can be disabled at the test, suite or global level."
I have not used this framework, but I came across it (and your questions) while researching this topic.

Is there a difference between commit and rollback in a transaction only having selects?

The in-house application framework we use at my company makes it necessary to put every SQL query into transactions, even though if I know that none of the commands will make changes in the database. At the end of the session, before closing the connection, I commit the transaction to close it properly. I wonder if there were any particular difference if I rolled it back, especially in terms of speed.
Please note that I am using Oracle, but I guess other databases have similar behaviour. Also, I can't do anything about the requirement to begin the transaction, that part of the codebase is out of my hands.
Databases often preserve either a before-image journal (what it was before the transaction) or an after-image journal (what it will be when the transaction completes.) If it keeps a before-image, that has to be restored on a rollback. If it keeps an after-image, that has to replace data in the event of a commit.
Oracle has both a journal and rollback space. The transaction journal accumulates blocks which are later written by DB writers. Since these are asychronous, almost nothing DB writer related has any impact on your transaction (if the queue fills up, then you might have to wait.)
Even for a query-only transaction, I'd be willing to bet that there's some little bit of transactional record-keeping in Oracle's rollback areas. I suspect that a rollback requires some work on Oracle's part before it determines there's nothing to actually roll back. And I think this is synchronous with your transaction. You can't really release any locks until the rollback is completed. [Yes, I know you aren't using any in your transaction, but the locking issue is why I think a rollback has to be fully released then all the locks can be released, then your rollback is finished.]
On the other hand, the commit is more-or-less the expected outcome, and I suspect that discarding the rollback area might be slightly faster. You created no transaction entries, so the db writer will never even wake up to check and discover that there was nothing to do.
I also expect that while commit may be faster, the differences will be minor. So minor, that you might not be able to even measure them in a side-by-side comparison.
I agree with the previous answers that there's no difference between COMMIT and ROLLBACK in this case. There might be a negligible difference in the CPU time needed to determine that there's nothing to COMMIT versus the CPU time needed to determine that there's nothing to ROLLBACK. But, if it's a negligible difference, we can safely forget about about it.
However, it's worth pointing out that there's a difference between a session that does a bunch of queries in the context of a single transaction and a session that does the same queries in the context of a series of transactions.
If a client starts a transaction, performs a query, performs a COMMITor ROLLBACK, then starts a second transaction and performs a second query, there's no guarantee that the second query will observe the same database state as the first query. Sometimes, maintaining a single consistent view of the data is of the essence. Sometimes, getting a more current view of the data is of the essence. It depends on what you are doing.
I know, I know, the OP didn't ask this question. But some readers may be asking it in the back of their minds.
In general a COMMIT is much faster than a ROLLBACK, but in the case where you have done nothing they are effectively the same.
The documentation states that:
Oracle recommends that you explicitly end every transaction in your application programs with a COMMIT or ROLLBACK statement, including the last transaction, before disconnecting from Oracle Database. If you do not explicitly commit the transaction and the program terminates abnormally, then the last uncommitted transaction is automatically rolled back. A normal exit from most Oracle utilities and tools causes the current transaction to be committed. A normal exit from an Oracle precompiler program does not commit the transaction and relies on Oracle Database to roll back the current transaction.
http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/statements_4010.htm#SQLRF01110
If you want o choose to do one or the other then you might as well do the one that is the same as doing nothing, and just commit it.
Well, we must take into account what an SELECT returns in Oracle. There are two modes. By default an SELECT returns data as that data looked in the very moment the SELECT statement started executing (this is default behavior in READ COMMITTED isolation mode, the default transactional mode). So if an UPDATE/INSERT was executed after SELECT was issued that won't be visible in result set.
This can be a problem if you need to compare two result sets (for example debta and credit sides of an general ledger app). For that we have a second mode. In that mode SELECT returns data as it looked at the moment the current transaction began (default behavior in READ ONLY and SERIALIZABLE isolation levels).
So, at least sometimes it is necessary to execute SELECTs in transaction.
Since you've not done any DML, I suspect there'd be no difference between a COMMIT and ROLLBACK in Oracle. Either way there's nothing to do.
I'd think a Commit would be more efficient; since generally you'd expect most DB transactions to be committed; so you would think the DB optimizes for this case (as opposed to trying to be more efficient for a rollback).