Connection hanged using transaction suspension with Websphere datasource - sql-server

While using websphere datasource to connect SQL-SERVER spring transaction getting hanged (Locked) with REQUIRES_NEW or NOT_SUPPORTED propogations.
This is not the case when using BasicDataSource or any other.
Please help.

REQUIRES_NEW and NOT_SUPPORTED are both transaction attributes that would prevent running the operation in the current transaction (which would be suspended and then resumed afterwards). The WebSphere Application Server data source is aware of container managed transactions and will enlist in them. I'm not sure what BasicDataSource is, but if it is not aware of container transactions, that could explain why you see a difference in behavior.
The flow to cause a single-thread deadlock could be something like this:
transaction begin
SQL command that locks row X
invoke REQUIRES_NEW method
implies transaction suspend, new transaction begin
SQL command that attempts to lock row X <-- deadlock here
If this is what you are seeing, it is operating as designed, per spec, and you should consider using a different transaction attribute, such as SUPPORTS, if you want the operation to run in the same transaction.

Related

SQL Azure - Transaction (Process ID 160) was deadlocked on lock resources with another process and has been chosen as the deadlock victim

We are experiencing the mentioned dead lock exception while doing CRUD on two SQL Server tables from parallel threads by calling Stored Procedures, here is the detailed scenario:
We have a desktop application where we are spinning up a code block in 100 - 150 parallel threads, the code block does insertion in TableA using SQL Bulk Copy and makes calls to three Stored Procedures, The stored procedures do insertion, updation and deletion in TableB based on some selection from TableA.
Soon as the application starts execution of the threads, SQL Server starts throwing the mentioned dead lock exception for a certain number of threads while some of the threads do run fine.
Exception Message:
Transaction (Process ID 160) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
Any help in this regard is appreciated in advance.
Thanks.
Is this SQL Server or SQL Azure/Azure SQL DB? If it's "box" SQL Server, you might consider ALTER DATABASE SET READ_COMMITTED_SNAPSHOT ON. This will enable read versioning. It's still possible to encounter deadlocks in this state, but it's as close to a silver bullet as you're likely to get.
Read versioning changes the concurrency model in some subtle ways, so be sure to read about it first and make sure it's compatible with your business logic: https://msdn.microsoft.com/en-us/library/tcbchxcb(v=vs.110).aspx
Otherwise, Srivats's other suggestion about minimizing transaction scope is not always simple to implement but is still solid. To that list, I would add: Ensure that you have well-indexed query access paths, and verify that none of the queries within your transactions require full table or index scans.
The message is clearly evident that Transaction (Process ID 160) was deadlocked on lock resources with another process.The lock could be on different levels. The locks are not getting released before another thread could lock that particular resource. Try to kill that Process Id and check the workflow if there are any lock conflicts.

Locking single row / row level when inserting data via TransactionScope, Entity Framework and SQL Server

I did some research and haven't found any explanation to this. So, If there's one out there, I'm sorry.
I am using TransactionScope to handle transactions with my SQL Server 2012 database. I'm also using Entity Framework.
The fact is that when I start a new transaction to insert a new record into my table, it locks the entire table, not just that row. So, if I run the Db.SaveChanges(), without committing it, and go to management studio and try to get the the already committed data from the same table, it hangs and return me no data.
What I would like in this scenario is to lock just the new row, not the entire table.
Is that possible?
Thank you in advance.
One thing to be very careful of when using TransactionScope is that it uses Serializable isolation level by default which can cause many locking issues in SQL Server. The default isolation level in SQL Server is Read Committed, so you should consider using that in any transactions that use TransactionScope. You can factor out a method that creates your default TransactionScope and always set to ReadCommitted by default (see Why is System.Transactions TransactionScope default Isolationlevel Serializable). Also ensure that you have a using block when using TransactionScope, to make sure that if errors occur with the transaction processing that the transaction is rolled back (http://msdn.microsoft.com/en-us/library/yh598w02.aspx).
By default, SQL Server uses a pessimistic concurrency model, which means that as DML commands are being processed (inserts, updates, deletes), it will acquire an exclusive lock on the data that is changing, which will prevent other updates or SELECTs from completing until those locks are released. The only way to release those locks is to commit or rollback the transaction. So if you have a transaction that is inserting data into a table, and you run a SELECT * FROM myTable before the insert has completed, then SQL Server will force your select to wait until the open transaction has been commit or rolled back before returning the results. Normally transactions should be small and fast, and you would not notice as much of an issue. Here is more info on isolation levels and locking (http://technet.microsoft.com/en-us/library/ms378149.aspx).
In your case, it sounds like you are debugging, and have hit a breakpoint in the code with the transaction open. For debugging purposes, you can add a nolock hint to your query, which would show the results of the data that has been committed, along with the insert which has not yet been committed. Because using nolock will return UN-committed data, be very careful about using this in any production environment. Here is an example of a query with a nolock hint.
SELECT * FROM myTable WITH(NOLOCK)
If you continue to run into locking issues outside of debugging, then you can also check out snapshot isolation (Great article by Kendra Little: http://www.brentozar.com/archive/2013/01/implementing-snapshot-or-read-committed-snapshot-isolation-in-sql-server-a-guide/). There are some special considerations when using snapshot isolation, such as tempdb tuning.

Does TransactionScope really need the "Distributed Transaction Coordinator" service running?

I am trying to understand the details of TransactionScope.
Below is quoted from here:
Some procedures in this topic use types in the System.Transactions
assembly. Before you follow these procedures, you must make sure that
the Distributed Transaction Coordinator service is running on the
computer where you run the unit tests. Otherwise, the tests fail, and
the following error message appears: "Test method
ProjectName.TestName.MethodName threw exception:
System.Data.SqlClient.SqlException: MSDTC on server 'ComputerName' is
unavailable".
But strange enough, I stopped that service, and did some DB deletion within a TransactionScope, and didn't call the Complete() method at the end, which means the transaction should rollback.
The DB is not affected indeed. It seems the transaction still works well.
As I understand, we need resource manager (RM) and transaction manager (TM) to make the transaction on resources happen. In my scenario, the Distributed Transaction coordinator service is stopped, who is the transaction manager then?
When you use TransactionScope, you are working with an ambient transaction, and the transaction is independently managed within your code.
The TransactionScope class is defined by msdn as:
Makes a code block transactional. This class cannot be inherited.
...
Upon instantiating a TransactionScope by the new statement, the
transaction manager determines which transaction to participate in.
Once determined, the scope always participates in that transaction.
The decision is based on two factors: whether an ambient transaction
is present and the value of the TransactionScopeOption parameter in
the constructor. The ambient transaction is the transaction your code
executes in. You can obtain a reference to the ambient transaction by
calling the static Current property of the Transaction class.
Also from msdn:
The TransactionScope class provides a simple way to mark a block of
code as participating in a transaction, without requiring you to
interact with the transaction itself. A transaction scope can select
and manage the ambient transaction automatically.
Also from msdn:
A TransactionScope object has three options:
Join the ambient transaction, or create a new one if one does not exist.
Be a new root scope, that is, start a new transaction and have that transaction be the new ambient transaction inside its own scope.
Not take part in a transaction at all. There is no ambient transaction as a result.
The DTC service is only needed when the transaction is escalated. See more on this here: Transaction Management Escalation
Escalation can be difficult to determine beforehand as by design, this is pretty automatic wich is cool but sometimes unexpected. But, basically, if you're running a transaction on a single SQL Server (not SQL 2000 I believe you need SQL 2005 at least or escalation always happens, see this link: TransactionScope: transaction escalation behavior) instance (one "Resource Manager" / RM), there are good chances that escalation will be avoided. And in general, it's a good thing because it can be costy in terms of performance.

Database Connection and Rollback Process

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.

Force MSDTC to orphan a SQLServer distributed transaction

When shutting down my project's WebSphere-based JavaEE application, distributed transactions are sometimes left alive in the SQLServer 2005 database. These retain their locks forever and must be killed manually. They are described generally in this very good article.
The article talks about how the transaction coordinator is unable to co-ordinate the distributed transaction participants and so flags the transaction with a process ID of -2.
Given that we get this issue infrequently, but that it always happens when we shut down the application, I am not convinced it is a failure of the MSDTC. It is more likely to have something to do with WebSphere and how it terminates applications.
I would like to test it. But I cannot reliably make it happen.
Is there any way to force the MSDTC to orphan a SQLServer distributed transaction?
My question was misleading, because I wasn't quite sure what the problem actually was. I suspect MSDTC is assisting WebSphere in transacting with MQ and SQLServer. The problem occurs when we perform an unclean shutdown of the WAS server and the vendor-provided part of our application tries to do some sort of cleanup and fails.
I suspect this question is not helpful to anyone else (unless they are using the Misys Message Manager in WebSphere on Windows) so apologies, dear reader, for wasting your time.
Orphaned DTC transactions can occur in case SQLServer sessions with open but not yet prepared DTC or XA transactions are closed. This may happen because of network interruption or due to unexpected application abort.
In this case SQLServer keeps the transaction with DTC and the SPID is -2.
The post on SQLServerCentral mentions that following query can be used to identify the orphaned transactions:
Select req_transactionUOW
from master..syslockinfo
where req_spid = -2
Exeuting "kill" with the UOW given as argument, will remove the active ransaction.
This behavior of SQLSever is very uncommon. Usually a session loss will abort any XA transaction.
The good news is that SQLServer provides an option that changes this behavior.
The trace flag 3924 can be set in order to achieve this. Just exec DBCC TRACEON(3924,-1) with "sa" privileges and SQLServer automatically removes transactions in case sessions get lost.
The trace flag will be lost on SQLServer restart. In order to get it set during SQLServer startup automatically add it in SQLServer configuration manager:
SQLServer Configuration Manager sceenshot

Resources