Mysql: ROLLBACK for multiple queries - mysql

I have more than three MySql queries in a PHP script triggered by scheduled task. If a query catch an error, script throw an exception and rollback that Mysql query. It works fine.
However if first query works fine, but not 2nd query, throw an exception, it rollback 2nd one but not 1st query.
I am using begin_trans(), commit and rollback() for individual queries because Sometimes i need to rollback one query, sometimes all queries. Is there any way to rollback one query or all queries?
Thanks in advance
UPDATE:
I got it working, there was no problem with in begin_trans(), commit and rollback(), the database connection config was different for one query from other queries, crazy code without any comments!!!

The only thing that has to be rolled back is a write operation (INSERT, UPDATE, or DELETE). I'll assume that you're using the word "query" to mean something other than a SELECT operation.
If you want several SQL statements to succeed or fail together, you'll need to specify a transaction.
UPDATE:
Now I'm confused; it's no wonder that you are.
A transaction is an all-or-nothing proposition. It sounds to me like you're confusing two separate use cases: one where you want a single query in a transaction and another where you want several in one transaction. Combining the two is confusing you and, I'm sure, your users.
One you commit a transaction, you can't roll it back. So you'll have to make up your mind: either operation A is part of its own transaction or grouped with B, C, and D in another. But not both.

A rollback is applied to all queries within current transaction.
[edited after question update]
MySQL currently does not support nested transaction so it's all or nothing deal. You can only rollback all queries within a transaction or commit all (successful ones).

The kind of rollback that one gets is completely dependent on how one defines the transaction.
And that is dependent on business use case.

Related

Are changes made to DB only through transactions?

I am not able to get a clear complete understanding regarding the role of transactions in databases.
I know operations clubbed in a transactions will be executed together and then either committed or rolled back.
But then what about about any other query that I write to the database without manually creating a transaction.
Is a transaction created internally for them?
Also what about select statements then? Are transactions created for them too?
I have been using database and sql for some time now, alas I am not clear on these
Are changes to DBs happening only through transactions? Short answer is yes.
There is always a transaction involved:
It might be automatically started (before) and commited (after) every single DML statement you issue, if you're relying on AUTOCOMMIT behaviour of your database session
Or you may explictly start one with BEGIN, execute your statements and end it with COMMIT
I like to think a transaction as a boundary that imposes clear semantics of ATOMICITY and ISOLATION to the statements that are contained within.
You describe atomicity (all or nothing behaviour) but that is not the only guarantee that a transaction can give you: there's also isolation (and this has to do with reads you within transactions (E.g. SELECTs).
In a concurrent application (many clients writing and reading to the same db/table at the same time), transaction ISOLATION is the property that defines "how much of the effects of other operations" can be observed in the current one. For example, assume you need to perform a transaction that involves doing the same SELECT multiple times: do you want this SELECT to return (possibly) different results each time (because some modification happened concurrently) or not?
For single statements is:
A single DML (UPDATE, INSERT...) statement by itself is effectively "As if it was in a transaction with a single statement, that gets immediately commited after execution" (Either it works like this because you're in AUTOCOMMIT, or you wrapped a single statement within BEGIN...COMMIT)
For a single SELECT it's the same. The transaction in this case (implicit or not, gives you the possibility of specifiying different isolation levels). It might sound strange to consider transactions for SELECTS, but requiring particular isolation levels might mean that the db is acquiring some lock to the data under the hood: committing the transaction in that case would release such lock.
Since you tagged mysql, here you can read on transaction isolations supported by mysql:
https://dev.mysql.com/doc/refman/5.7/en/innodb-transaction-isolation-levels.html
A SQL transaction is any statement that contains Data Manipulation Language (DML). That is, any statement that changes values in a table, such as UPDATE, INSERT, MERGE, DELETE, etc.

MySQL Transaction

It could be a dumb question, and tried to search for it and found nothing.
I been using mysql for years(not that to long) but i never had tried mysql transactions.
Now my question is, what would happen if i issue an insert or delete statement from multiple clients using transactions? does it would lock the table and prevent other client to perform there query?
what would happen if other client issue a transaction query while the other client still have unfinished transaction?
I appreciate for any help will come.
P.S. most likely i will use insert using a file or csv it could be a big chunk of data or just a small one.
MySQL automatically performs locking for single SQL statements to keep clients from interfering with each other, but this is not always sufficient to guarantee that a database operation achieves its intended result, because some operations are performed over the course of several statements. In this case, different clients might interfere with each other.
Source: http://www.informit.com/articles/article.aspx?p=2036581&seqNum=12

MySQL Under High Load, Race Condition?

I am experiencing what appears to be the effects of a race condition in an application I am involved with. The situation is as follows, generally, a page responsible for some heavy application logic is following this format:
Select from test and determine if there are rows already matching a clause.
If a matching row already exists, we terminate here, otherwise we proceed with the application logic
Insert into the test table with values that will match our initial select.
Normally, this works fine and limits the action to a single execution. However, under high load and user-abuse where many requests are intentionally sent simultaneously, MySQL allows many instances of the application logic to run, bypassing the restriction from the select clause.
It seems to actually run something like:
select from test
select from test
select from test
(all of which pass the check)
insert into test
insert into test
insert into test
I believe this is done for efficiency reasons, but it has serious ramifications in the context of my application. I have attempted to use Get_Lock() and Release_Lock() but this does not appear to suffice under high load as the race condition still appears to be present. Transactions are also not a possibility as the application logic is very heavy and all tables involved are not transaction-capable.
To anyone familiar with this behavior, is it possible to turn this type of handling off so that MySQL always processes queries in the order in which they are received? Is there another way to make such queries atomic? Any help with this matter would be appreciated, I can't find much documented about this behavior.
The problem here is that you have, as you surmised, a race condition.
The SELECT and the INSERT need to be one atomic unit.
The way you do this is via transactions. You cannot safely make the SELECT, return to PHP, and assume the SELECT's results will reflect the database state when you make the INSERT.
If well-designed transactions (the correct solution) are as you say not possible - and I still strongly recommend them - you're going to have to make the final INSERT atomically check if its assumptions are still true (such as via an INSERT IF NOT EXISTS, a stored procedure, or catching the INSERT's error in the application). If they aren't, it will abort back to your PHP code, which must start the logic over.
By the way, MySQL likely is executing requests in the order they were received. It's possible with multiple simultaneous connections to receive SELECT A,SELECT B,INSERT A,INSERT B. Thus, the only "solution" would be to only allow one connection at a time - and that will kill your scalability dead.
Personally, I would go about the check another way.
Attempt to insert the row. If it fails, then there was already a row there.
In this manner, you check or a duplicate and insert the new row in a single query, eliminating the possibility of races.

Before commiting the transaction, what happens to the queries on a tables which are being used in that transaction?

I have a situation where I need to lock 2 tables, until some operations are done on those 2 tables individually. For that I have chosen "TRANSACTIONS".
So, between "START TRANSACTION" and "COMMIT".. if anyone tries to insert into those tables, what happens to those queries? will they be maintained in the queue and will be executed after the transaction is completed?
Ideally, whats my requirement is.. they should not get inserted until my transaction has got commited.
Please anyone tell me the scenario.
Thanks in advance!
SuryaPavan
When a transaction is initiated, it's isolated from the rest of the world. That's the I in ACID.
During the transaction, if anyone tries to insert anything - the insert will occur but it won't break the transaction you are performing in any way. Same rule applies in the other direction.
If you have the requirement to literally lock the entire table for insert until your transaction succeeds - that smells like a bad design and you should reconsider if what you're doing is really optimal.
If they got inserted before your transaction was committed (that is, in the middle of your transaction), that would make transactions fairly useless.
I assume you're using mysql (since your question is tagged with that)... why not open two command line sessions to your database and try it to see what happens? That would take far less time than posting your question and waiting for an answer, and you'll likely learn more in the process.

mysql: working around implicit transaction commits?

I wrote a tool for our project, for applying sql update files that were committed, to the DB. Whenever run (on deployment), it calculates the list of update files which need to be applied, and applies them iniside a transaction.
Recently I became aware of an issue: mysql would implicitly commit a transaction, whenever DDL statements (like create) are executed. http://dev.mysql.com/doc/refman/5.0/en/implicit-commit.html
This is an issue for me, as sometimes an sql update file contains several statements, which as I understand will result in committing the transaction in the middle of executing the update file. This is a problem, because whenever a subsequent update will fail (which happens from time to time) I want to be able to rollback the transaction, or at least track which update files where applied (completely) and which were not.
Is there a way around the implicit transactions issue? I.e. is there a way to rollback a sequence of DDL statements whenever one of them fail?
Any other suggestions how I can handle the issue?
Thanks
Gidi
No. MySQL does not support transactional DDL. You either need to separate your DDL statements from DML statements, or perhaps try to use migration tool like RuckUsing