Do MySQL databases implement Transactions by Default? - mysql

I was wondering what happens when several users try to UPDATE a MySQL database at the same time. Went online and learnt about Transactions.
Do I need to define the transactions statements.(START TRANSACTION,... COMMIT/ROLLBACK) for every one of my database UPDATE queries? Is there an automated way to achieve this?

By default , MySQL has autocommit enabled, which can be toggled off using
set session autocommit=off;
For transaction based queries like banking, manual use of TRANSACTION is executed, which ignores the autocommit setting. e.g:
START TRANSACTION;
update bank_card set balance=balance-100;
update credit_card set balance=balance+100;
ROLLBACK; -- execute rollback to cancel the transaction if necessary
COMMIT;
Should something went wrong in any of the UPDATE statements,by executing ROLLBACK; the transaction is aborted and no UPDATE is performed.
When several users try to UPDATE the same table, MySQL will place a LOCK on related rows which prevents simultaneous writing. The first UPDATE query will release the lock by either committing (successful) or rolling back (usually something went wrong) before the second update query can acquire the lock and do the UPDATE.

Related

Do a dry run to see if a database row is locked or not

Let's say I am trying to execute the following UPDATE statement in mysql (Innodb):
UPDATE main SET name = "Ralph" WHERE rowid=19283
Is there a way before doing this statement to see if there is a row/table-level lock on rowid=19283 before running this update? Or is the application strategy of dealing with deadlocks to catch the exception and then deal with them after the fact? I find that once a deadlock is reached, it's often impossible to update that row without some very loop-y logic, and so I'm seeing if the deadlock can be detected before the potential UPDATE/INSERT statement
A common pattern is
BEGIN;
SELECT ... FOR UPDATE; -- grab a lock on the row
... do some other processing, then eventually:
UPDATE ... -- change the row (or maybe skip this in some cases)
COMMIT;
This allows multiple connections to gracefully change that row, but without stepping on each other.
No, this does not eliminate deadlocks. It may turn a deadlock into a "lock wait", which is fine.
And it is not quite a "dry run". It moves the lock from the UPDATE back to the SELECT. If there are other things going on in this, and the competing, transaction, there could be a deadlock.
If you have 2 connections doing that transaction at "exactly" the same time, one will wait until the other finishes. (No deadlock.)

MySql: SELECT ... FOR UPDATE break before doing the UPDATE

I'm doing a SELECT ... FOR UPDATE to lock one record, then doing some calculations and then doing the actual UPDATE. I'm working on an InnoDB-database.
But the calculations might end up in a state where I do not want to execute the UPDATE. How do I cancel the lock in this situation?
InnoDB is made for this. You need to manage your transactions.
Before doing your SELECT ... FOR UPDATE, do START TRANSACTION.
Then do your SELECT ... FOR UPDATE.
Then do the rest of your database work.
Then do COMMIT.
If you decide you don't want to complete your update work, do ROLLBACK instead of COMMIT, and every change within your transaction is discarded. The database returns to the state right before START TRANSACTION.
Don't forget the COMMIT or ROLLBACK especially when debugging. If you do forget, your database may appear to lock up, because a future SELECT ... FOR UPDATE operation may wait for your COMMIT. (Don't ask how I know this. :-)

MySQL Workbench: Start Transaction seems to be committed before rollback

I wrote a bunch of delete statements and wrapped them in a transaction:
start transaction;
delete a...
delete b...
delete c...
rollback;
The idea is I would want the deletes to occur inside a transaction which would rollback upon completion. If a step failed along the way, I would want the successful steps to be rolled back as well.
To my chagrin delete a worked, removing a few thousand rows, delete b failed, but when I reran the statements all the records from a appeared to be gone.
Is this because the transaction is still open? I tried doing:
set session transaction isolation level read committed;
select a.*
and got back zero rows so I think that is not the case. Was the successful a delete committed? And if so, how do I prevent that from happening until I can guarantee a full working query?
MySQL Workbench enables auto commit by default. In the SQL editor there is a toolbar button that can be used to toggle auto commit at will:
Somebody turned me on to, what I think, is a better way to do this:
begin;
<sql transactions>
commit;
Try setting the autocommit flag to false:
set ##autocommit = false;
start transaction;
delete a...
delete b...
delete c...
rollback;

Do "SELECT ... LOCK IN SHARE MODE" and "SELECT ... FOR UPDATE" have to be inside of a transaction?

I'm reading the documentation for these commands and am confused. The descriptions for the commands mention transactions:
SELECT ... LOCK IN SHARE MODE sets a shared mode lock on any rows that
are read. Other sessions can read the rows, but cannot modify them
until your transaction commits. If any of these rows were changed by
another transaction that has not yet committed, your query waits until
that transaction ends and then uses the latest values.
For index records the search encounters, SELECT ... FOR UPDATE blocks
other sessions from doing SELECT ... LOCK IN SHARE MODE or from
reading in certain transaction isolation levels. Consistent reads will
ignore any locks set on the records that exist in the read view. (Old
versions of a record cannot be locked; they will be reconstructed by
applying undo logs on an in-memory copy of the record.)
But then the examples don't show transactions being used. Running a test command such as select * from users for update; without a transaction doesn't result in any errors (it works). Does this mean transactions don't have to be used with these commands? If so, is there any advantage to putting these commands inside of a transaction?
In InnoDB each query is effectively run in a transaction. If you don't start transaction explicitly (with start transaction or by setting autocommit to off), each transaction is committed after the query run. This means that if you are not in a transaction, the lock acquired with SELECT ... IN SHARE MODE will be released as soon as the query is completed. There is nothing that prevents you from doing this, it just doesn't make much sense to use locks outside of a transaction; as these locks are to guarantee that the value you select won't change until a later query you are going to execute (like if you want to insert/update data in one table based on the values in another)
A transaction ensures that all the commands it contains will either run successfully or rollback.
These types of select statements affect other transactions in other sessions. So basically wrapping these in transactions is only a matter of whether you are selecting the data as part of a larger set of commands.
If you only want to select the data you should either use the shared lock or no lock at all and no need to begin a transaction.

Working of Transactions in INNODB engine

Consider a transaction T1,
Start transaction;
Update emp set emp_id=1 where emp_id=3;
commit;
The engine i am using is INNODB engine.
Before commit operation of the above shown transaction, I had accessed the table again it is showing the previous committed values. If the Row Level locking is placed on the table, it might have shown the error (you cannot access while some transaction is in the middle). Is there any wrong in my understanding.? Can any one help me on this?
Anything that is done as a part of a transaction is available to the same transaction even before the transaction is committed. The changes are not available in other transactions.
To test this, you need to update in one transaction and then from another terminal start a new transaction and try to access. The second transaction will be able to read the data but if you try to update the update will block and wait for the first transaction to be committed.
If you want the second select to wait and return the updated data you should use select for update.