Deal with deadlocks in MySQL/InnoDB - mysql

I'm benchmarking MySQL under different isolation levels.
For the case of SERIALIZABLE I frequently get this error: "Deadlock found when trying to get lock; try restarting transaction at the client side".
Reading http://dev.mysql.com/doc/refman/5.6/en/innodb-deadlocks.html didn't help me much.
I have the following question:
What is the state of the database whenever I get the message ? Everything is frozen and the system expects from me to do something or my transaction has been already aborted and I just get informed about it ?
I'm using jdbc driver to connect to MySQL. Supposed my policy is to re-issue such failing transactions, do I need to call connection.rollback() or MySQL has already done that for me ?

In the case of a deadlock, MySQL will detect it and automatically roll back transactions as necessary to break the deadlock. It favors rolling back smaller transactions (affected rows).
If your transaction is rolled back, it is assumed that you will re-issue the transaction. MySQL does not do it for you.
When you receive such an alert, MySQL is not waiting on anything. It has already performed the rollback.

Related

ER_LOCK_DEADLOCK called when there is no lock

Logs showing that from time to time this error is raised.
I'm reading the docs and it's very confusing because we're not locking any tables to do inserts and we have no transactions beyond individual SQL calls.
So - might this be happening because we're running out of the mySQL connection pool in Node? (We've set it to something like 250 simultaneous connections).
I'm trying to figure out how to replicate this but having no luck.
Every query not run within an explicit transaction runs in an implicit transaction that immediately commits when the query finishes or rolls back if an error occurs... so, yes, you're using transactions.
Deadlocks occur when at least two queries are in the process of acquiring locks, and each of them holds row-level locks that they happened to acquire in such an order that they each now need another lock that the other one holds -- so, they're "deadlocked." An infinite wait condition exists between the running queries. The server notices this.
The error is not so much a fault as it is the server saying, "I see what you did, there... and, you're welcome, I cleaned it up for you because otherwise, you would have waited forever."
What you aren't seeing is that there are two guilty parties -- two different queries that caused the problem -- but only one of them is punished. The query that has accomplished the least amount of work (admittedly, this concept is nebulous) will be killed with the deadlock error, and the other query happily proceeds along its path, having no idea that it was the lucky survivor.
This is why the deadlock error message ends with "try restarting transaction" -- which, if you aren't explicitly using transacrions, just means "run your query again."
See https://dev.mysql.com/doc/refman/5.6/en/innodb-deadlocks.html and examine the output of SHOW ENGINE INNODB STATUS;, which will show you the other query -- the one that helped cause the deadlock but that was not killed -- as well as the one that was.

Mysql deadlock : what does 'try restarting transaction' mean and what exactly happens to the locked transactions [duplicate]

This question already has answers here:
Restarting transaction in MySQL after deadlock
(4 answers)
Closed 8 years ago.
I have a situation where 2 transactions create a mysql deadlock.
The following error is fired : Deadlock found when trying to get lock; try restarting transaction
If I'm correct, this error means that mysql deadlock timeout is expired, and mysql try to do something to removes this deadlock.
What isn't clear for me is what means try restarting transaction ? How a transaction can be "restarted" ?
What happens to the 2 locked transactions ? Are they both canceled (roll-backed) ? Or is it just one of them that is canceled so the lock can be released.
Thanks in advance
There is no deadlock timeout (though there are lock timeouts). If a deadlock is detected, no amount of time will resolve it, so MySQL reacts immediately.
MySQL will roll back one or more transactions until the deadlock is resolved.
From MySQL docs:
InnoDB tries to pick small transactions to roll back, where the size
of a transaction is determined by the number of rows inserted,
updated, or deleted.
It is up to your application that is making the SQL call to retry the transaction.
MySQL has some recommendations in its documentation How to Cope with Deadlocks.
If you wish to try to avoid the deadlock and are having trouble understanding the cause of the deadlock, I recommend starting another question, and posting the complete affected queries and schema, and ideally the deadlock report from SHOW ENGINE INNODB STATUS.

How do I avoid MySql deadlocks?

I'm talking to a MySql database using the jOOQ database abstraction layer.
I keep getting the following error:
SQL [null]; Deadlock found when trying to get lock; try restarting transaction
This is during a bulk insert of about 500 rows into a table. It is likely that more than one of these bulk inserts will be attempted at a time from different threads.
What is causing the deadlock, and how can I avoid it?
A traditional deadlock is when a transaction is trying to lock A and then B where another is trying to lock B and then A, leading to a situation where neither can complete. MySQL produces another sort of deadlock when there are too many pending locks on a particular resource.
You should check SHOW PROCESSLIST to see how many "waiting for lock" processes you have. It could be that the ones that fail are simply out of luck because there's too many in line.

MySQL configuration for multiple-threading transactions

I have 6 scripts/tasks. Each one of them starts a MySQL transaction, then do its job, which means SELECT/UPDATE/INSERT/DELETE from a MySQL database, then rollback.
So if the database is at a given state S, I launch one task, when the task terminates, the database is back to state S.
When I launch the scripts sequentially, everything works fine:
DB at state S
task 1
DB at state S
task 2
DB at state S
...
...
task 6
DB at state S
But I'd like to speed up the process by multiple-threading and launching the scripts in parallel.
DB at state S
6 tasks at the same time
DB at state S
Some tasks randomly fail, I sometimes get this error:
SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction
I don't understand, I thought transactions were meant for that. Is there something I'm missing ? Any experience, advice, clue is welcome.
The MySQL configuration is:
innodb_lock_wait_timeout = 500
transaction-isolation = SERIALIZABLE
and I add AUTOCOMMIT = 0 at the beginning of each session.
PS: The database was built and used under the REPEATABLE READ isolation level which I changed afterwards.
You can prevent deadlocks by ensuring that every transaction/process does a SELECT...FOR UPDATE on all required data/tables with the same ORDER BY in all cases and with the same order of the tables itself (with at least repeateable read isolation level in MySQL).
Apart from that, isolation levels and transactions are not meant to handle deadlocks, it is vice versa, they are the reason why deadlocks exist. If you encounter a deadlock, there are good chances that you would have an inconsistent state of your dataset (which might be much more serious - if not, you might not need transactions at all).

Deadlock issue with SQL Server 2008 and ADO.NET

In our applications we don't use either ADO.NET transaction or SQL Server transactions in procedures and now we are getting the below error in our website when multiple people are using.
Transaction (Process ID 73) was deadlocked on lock | communication buffer resources with another process and has been chosen as the deadlock victim. Rerun the transaction
Is this error due to the lack of transactions? I thought the consistency will be handled by the DB itself.
And one thing I noticed that SQLCommand.Timeout property has set to 10000. Will this be an issue for the error?
I am trying to solve this issue ASAP. Please help.
EDIT
I saw the Isolationlevel property of ADO.NET transaction, so if I use ADO.NET transaction with proper isolationlevel property like "ReadUncommitted" during reading and "Serializable" during writing?
Every SQL DML (INSERT, UPDATE, DELETE) or DQL (SELECT) statement runs inside a transaction. The default behaviour for SQL Server is for it to open a new transaction (if one doesn't exist), and if the statement completes without errors, to automatically commit the transaction.
The IMPLICIT_TRANSACTIONS behaviour that Sidharth mentions basically gets SQL Server to change it's behaviour somewhat - it leaves the transaction open when the statement completes.
To get better information in the SQL Server error log, you can turn on a trace flag. This will then tell you which connections were involved in the deadlock (not just the one that got killed), and which resources were involved. You may then be able to determine what pattern of behaviour is leading to the deadlocks.
If you're unable to determine the underlying cause, you may have to add some additional code to your application - that catches sql errors due to deadlocks, and retries the command multiple times. This is usually the last resort - it's better to determine which tables/indexes are involved, and work out a strategy that avoids the deadlocks in the first place.
IsolationLevel is your best bet. Default serialization level of transactions is "Serializable" which is the most stringent and if at this level there is a circular reference chances of deadlock are very high. Set it to ReadCommitted while reading and let it be Serializable while writing.
Sql server can use implicit transactions which is what might be happening in your case. Try setting it off:
SET IMPLICIT_TRANSACTIONS OFF;
Read about it here: http://msdn.microsoft.com/en-us/library/ms190230.aspx