I just read in Wikipedia, that SQL is inherently transactional.
I took this to mean that every statement made to a SQL DBMS is treated as a transaction by default. Is this correct?
An example I can think of that might make this question relevant would be if you considered an update statement like this:
UPDATE Employee SET salary=salary * 1.1 WHERE type='clerk';
If this were being processed and there was some failure that caused the DBMS to shutdown, on restart, in a transactional sense, wouldn't the rows that records that were updated be rolled back?
At least in SQL Server, if you run a transaction, opening the line with
BEGIN TRAN
and you don't commit or rollback the transaction, it will ask you (if you try to exit the window) if you want to commit the transactions. If something caused everything to crash, and we had an open transaction (meaning, nothing to close it), it would not be considered committed.
Your question demonstrates another reason why many developers will use a COMMIT TRAN only if there are no errors, so every transaction by default, will rollback.
Disclaimer here: I am ONLY referring to SQL Server - I cannot say this would hold true for other SQL databases.
The answer is no. SQL is a language, what you describe is ACID behaviour. Though many database systems behave that way, it is still perfectly possible to create one that uses SQL as language and allows statements to be partially executed.
Related
My web application is connected to a SQL Server 2016 Express database, and we have been plagued by data locks in certain areas of the system.
My colleague noticed just today that, when a KILL process was used to kill a long-running transaction, that several transactions that had ostensibly already been committed were rolled-back.
I have checked using #vladV's script on In SQL Server, how do I know what transaction mode I'm currently using? that in fact the database seems to be in auto-commit mode.
So therefore it must be that that something in the database is opening a new transaction and not committing it.
So I found in the database four stored procedures which contain the following
SET IMPLICIT_TRANSACTIONS ON
... code ...
IF ##TRAN_COUNT>0 COMMIT WORK
Am I right in saying that in some/most situations such a stored procedure would leave transactions open, even after exiting the stored procedure, and that this could be the source of the data-lock problems?
And if so, then could I just remedy the code by doing
SET IMPLICIT_TRANSACTIONS OFF
when the stored procedure exits?
Am I right in saying that in some/most situations such a stored procedure would leave transactions open
Some. Depends on what comes after. With IMPLICIT TRANSACTIONS in SQL Server, transactions are not automatically started until you run a query that reads the database.
could I just remedy the code by doing SET IMPLICIT_TRANSACTIONS OFF
No. That won't end any open transactions.
Note that COMMIT doesn't reduce the ##trancount to 0. It decrements it by 1. So if you have multiple BEGIN TRAN statements, or an explicit BEGIN TRAN after an transaction has implicitly begun, then you will need multiple COMMITs.
You might try
WHILE ##trancount > 0 COMMIT TRANSACTION
which will definitely commit any outstanding transactions.
I wonder a case. I have a project using a database (Oracle and Mssql). My project has a framework that I manage transactions.
In thread I open a database connection and start a transaction.(In transaction, there are many update and insert queries.) While code is running, somehow connection is closed. Because I have try-catch block, I catch exception and rollback transaction. BUT; if my connection is closed because some reasons, how rollback query can run on database? How can I handle this situation? If I open a new connection and rollback, does it work?
Thanks.
There is a term you should know - ACID compliancy:
Atomicity is an all-or-none proposition;
Consistency guarantees that a transaction never leaves your database in a half-finished state.
Isolation keeps transactions separated from each other until they’re finished.
Durability guarantees that the database will keep track of pending changes in such a way that the server can recover from an abnormal termination.
Concerning MySQL
In order to get this at MySQL, you have to use Transaction Safe Tables (TST). Advantages of Transaction-Safe Tables:
Safer. Even if MySQL crashes or you get hardware problems, you can get your data back, either by automatic recovery or from a backup + the transaction log.
You can combine many statements and accept these all in one go with the COMMIT command.
You can execute ROLLBACK to ignore your changes (if you are not running in auto-commit mode).
If an update fails, all your changes will be restored.
Concerning SQL Server
You should read "Transaction Behavior On Lost Connection" MSDN forum topic.
To understand better what lays behind MS SQL Server transactions, read a good article "Locks and Duration of Transactions in MS SQL Server"
Make sure you are not using any autocommit feature (I think that's enabled by default in some MySQL installations). If you do all your commits "manually", a broken connection will just result in you never committing the transaction and so it won't ever get written.
You cannot reconnect to rollback in most database systems.
I have recently tried a big merge of 2 databases. We recreated the schema from Database 2 into Database 1 and created a script to transfer all data from database 2 into Database 1. This script takes about 35 min to run and have transaction handling with:
BEGIN TRANSACTION
...
IF(##error<>0)
COMMIT TRANSACTION
ELSE
ROLLBACK TRANSACTION
The full script is a bit sensitive but here is some SQL that have the same structure: http://pastebin.com/GWJ3ZnkF
We ran the script and all data was transfered without errors. We tested the systems running with the new combined database (removed access rights to the old database).
But as a last task we wanted to take the old database offline to make sure no one used that database. To do this we used:
ALTER DATABASE <dbname> SET OFFLINE WITH ROLLBACK IMMEDIATE
This was bad. After this line of SQL code all data in the combined database that we just copied was suddenly gone. I first asumed it wasn't really finished so the "Rollback immediate" sounds like it have performed a rollback on my transaction..
But why? Wasn't the transaction allready committed?
Also I tried running the same script again a few times but after every attempt no data was copied even if it said the script was successfull. I have no idea why... did it remember my offline rollback somehow?
What is really happening to my connections?
Sounds like you had a pending transaction uncommitted and you forced it to rollback, loosing some of the work. The rest is explained by how your scripts are structured. Is unlikely your script had a single transaction from start to bottom. Only the last transaction was rolled back, so the database was left now in a state in which it is 'half copied'. Probably your script does various checks and this intermediate state sends the script on the 'ELSE' branches where it does not do the proper work (ie. apparently does nothing).
W/o posting the exact script, is all speculation anyway.
Right now you need to restore the database to a consistent state, the one before your data copy. Use the backup you took before the data move (you did take a backup, right?). for extra credit, make sure your script is idempotent and works correctly on a half-updated database.
I'd double-check to make sure that there are no outstanding transactions. Either go through the file and count the number of BEGIN TRANSACTION vs COMMIT TRANSACTION lines, or add a statement to the end of it to SELECT ##TRANCOUNT to ensure that there are no open transactions remaining.
If your data has been committed, there should be no way it can be lost by disconnecting you.
WITH ROLLBACK IMMEDIATE:
All incomplete transactions will be rolled back and any other
connections to the database will be
immediately disconnected.
Sounds like someone got the 2 databases mixed up or maybe there is an outstanding transaction?.... Can you post your entire script?
Ref: ALTER DATABASE.
Rather than only checking ##ERROR, inspect ##TRANCOUNT as well.
When you create a SQL Server transaction, what gets locked if you do not specify a table hint? In order to lock something, must you always use a table hint? Can you lock rows/tables outside of transactions (i.e. in ordinary queries)? I understand the concept of locking and why you'd want to use it, I'm just not sure about how to implement it in SQL Server, any advice appreciated.
You should use query hints only as a last resort, and even then only after expert analysis. In some cases, they will cause a query to perform badly. So, unless you really know what you are doing, avoid using query hints.
Locking (of various types) happens automatically everytime you perform a query (unless NOLOCK is specified). The default Transaction Isolation level is READ COMMITTED
What are you actually trying to do?
Understanding Locking in SQL Server
"Can you lock rows/tables outside of transactions (i.e. in ordinary queries)?"
You'd better understand that there are no ordinary queries or actions in SQL Server, they are ALL, without any exceptions, transactional. This is how ACID-ness is achieved, see, for ex., [1]. If client tools or developer interactively do not specify transaction explicitly with BEGIN TRANSACTION and COMMIT/ROLLBACK, then implicit transactions are used.
Also, transaction is not synonym of locking/locks engagement. There is a plethora of mechanisms to control concurrency without locking (for example, versioning. etc.) as well as READ UNCOMMITTED transaction "isolation" (in this case, absence of any isolation) level does not control it at all.
Update2:
In order to lock something, must you always use a table hint?
As far as, transaction isolation level is not READ UNCOMMITTED or one of row-versioning (snapshot) isolation levels, for ex., default READ COMMITTED or set by, for ex.,
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
the locks are issued (I do not know where to start and how to end this topic[2]). Table hints, which can be used in statements, override these settings.
[1]
Paul S. Randal. Understanding Logging and Recovery in SQL Server
What is Logging?
http://technet.microsoft.com/en-us/magazine/2009.02.logging.aspx#id0060003
[2]
Insert trailing ) upon clicking this link
http://en.wikipedia.org/wiki/Isolation_(database_systems)
Update:
5 min ago I had reputation 784 (the same as 24h ago) and, now, without any visible downvotes, it dropped to 779.
Where can I ask this question if I am banned from meta.stackoverflow.com?
What is the equivalent to the following SQL Server statements in DB2?
Begin Transaction
Commit Transaction
Rollback Transaction
The answer is actually a little more complicated than indicated here. True, transactions are ANSI standardized, and DB2 may support them.
DB2 for z/OS can be a very different beast from the other variants (LUW, Linux-Unix-Windows, being the most common). At risk of sliding into a rant, this makes the idea of talking about DB2 almost pointless. You are talking about some specific variant of IBM's database, but what works in one can be completely invalid in another. I will assume that whatever flavor the OP was using was not the z/OS one, since the BEGIN TRANSACTION answer was accepted.
For those of you who stumble across this trying to use transactions with DB2 z/OS, here is the rundown: DB2 for the mainframe does not have explicit transactions. There is no BEGIN TRANSACTION or any other comparable construct. Transactions are begun implicitly (usually referred to as a unit of work in the docs) and committed or rolled back explicitly (usually--many GUI tools, like Toad, have an autocommit feature that can sneak up on you once in a while).
From the 9.1 z/OS SQL reference manual (page 28; available at http://www-01.ibm.com/support/docview.wss?uid=swg27011656#manuals):
"A unit of work is initiated when an application process is initiated. A unit of work
is also initiated when the previous unit of work is ended by something other than
the end of the application process. A unit of work is ended by a commit operation,
a full rollback operation, or the end of an application process. A commit or rollback
operation affects only the database changes made within the unit of work it ends."
The closest thing you get when writing scripts is to manually specify a savepoint.
These look like this:
SAVEPOINT A ON ROLLBACK RETAIN CURSORS;
UPDATE MYTABLE SET MYCOL = 'VAL' WHERE 1;
ROLLBACK WORK TO SAVEPOINT A;
Superficially, these resemble explicit transactions, but they are not. Instead, they really are just points in time within a single implicit transaction. For many purposes, they may suffice, but it is important to be aware of the conceptual differences.
See here for more info. But basically
BEGIN TRANSACTION
COMMIT TRANSACTION
ROLLBACK
If you use an IDE like Intellij Idea (or others) then you don't have the possibility to start explicitely a transaction. In others words you cannot type 'begin transaction' in the console of your IDE.
But you can disable 'Auto-commit' (and reenable it later) and then type 'commit' or "rollback' into the console.
In IDEA there is also a button to 'commit' and a button to 'rollback'.
Have a look to the screen dump attached.