Are sql statements such as CREATE TABLE tbl_name ..... allowed in transactions.
For example:
begin;
CREATE TABLE .......;
sdfghjk;
rollback;
The table is still created despite a statement in the transaction failing, and a rollback at the end. Is there a way to prevent the table from being created if a statement in the transaction fails?
DDL statements are allowed within transactions, but are not generally impacted by the transactions. From the MySQL Documentation on what can and cannot be rolled back:
Some statements cannot be rolled back. In general, these include data
definition language (DDL) statements, such as those that create or
drop databases, those that create, drop, or alter tables or stored
routines.
You should design your transactions not to include such statements. If
you issue a statement early in a transaction that cannot be rolled
back, and then another statement later fails, the full effect of the
transaction cannot be rolled back in such cases by issuing a ROLLBACK
statement.
Source
If you still need to use table you can do create temporary table..... It doesn't commit transaction but will be deleted when connection will be closed.
Related
I have a Spring / JDBC application that relies heavily on MySQL rollback for unit tests. I'm finding that if I perform certain DDL operations - even on temporary tables - in those transactions, the rollback fails even on normal DML statements. For example:
#Test
#Rollback(true)
public void testRollbackProblem() {
template.update("create temporary table foo (id INTEGER )");
template.update("update forms set form_name = 'blah' where form_id = 1412");
template.update("alter table foo add (name text)");
}
After this test completes, that middle statement will be persisted and not rolled back. Is there a way to prevent that? Perhaps certain parameters passed to the alter statement?
This is MySQL limitations as far I know. CREATE TABLE and ALTER TABLE statements cause an implicit commit and can not be rolled back:
The CREATE TABLE statement in InnoDB is processed as a single transaction. This means that a ROLLBACK from the user does not undo CREATE TABLE statements the user made during that transaction.
See also MySQL documentation: https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html
Updated:
Because you're using CREATE TEMPORARY TABLE it actually shouldn't do implicit commit but it happens because when you're executing ALTER TABLE:
CREATE TABLE and DROP TABLE statements do not commit a transaction if the TEMPORARY keyword is used. (This does not apply to other operations on temporary tables such as ALTER TABLE and CREATE INDEX, which do cause a commit.) However, although no implicit commit occurs, neither can the statement be rolled back, which means that the use of such statements causes transactional atomicity to be violated. For example, if you use CREATE TEMPORARY TABLE and then roll back the transaction, the table remains in existence.
I'm debugging a complex complex stored procedure. I need to insert my prepared queries and their results in a debugging table but as whole of this procedure in enclosed between a BEGIN TRANSACTIN and COMMIT then nothing will be stored in my logging tables until COMMIT. So I can not find cause of problem if it raises an error and everything ROLLBacks.
Unfortunately MySQL doesn't have autonomous transactions, but for log tables you can use the MyISAM storage engine. MyISAM doesn't have transactions, so in case of a rollback data inserted in a MyISAM log table isn't "lost".
I would like to create a table and perform an insertion all in one transaction. Can this be done in MySQL?
According to MySQL:
Some statements cannot be rolled back. In general, these include data definition language (DDL) statements, such as those that create or drop databases, those that create, drop, or alter tables or stored routines.
Documentation
No, MySQL (well, InnoDB) does not support transactions for DDL statements.
I quickly browsed MySQL manual but didn't find the exact information about my question. Here is my question: if I have a InnoDB table A with two triggers triggered by 'AFTER INSERT ON A' and 'AFTER UPDATE ON A'. More specifically, For example: one trigger is defined as:
CREATE TRIGGER test_trigger AFTER INSERT ON A
FOR EACH ROW
BEGIN
INSERT INTO B SELECT * FROM A WHERE A.col1 = NEW.col1
END;
You can ignore the query between BEGIN AND END, basically I mean this trigger will insert several rows into table B which is also a InnoDB table.
Now, if I started a transaction and then insert many rows, say: 10K rows, into table A. If there is no trigger associated with table A, all these inserts are atomic, that's for sure. Now, if table A is associated with several insert/update triggers which insert/update many rows to table B and/or table C etc.. will all these inserts and/or updates are still all atomic?
I think it's still atomic, but it's kind of difficult to test and I can't find any explanations in the Manual. Anyone can confirm this?
And by atomic, you mean if one statement in the trigger fails, the whole statement fails. Yes -- the trigger is done in the context of statement's transaction. And no, of course, if there is no transaction, then there is no transaction context.
For transactional tables, failure of a statement should cause rollback of all changes performed by the statement. Failure of a trigger causes the statement to fail, so trigger failure also causes rollback. For nontransactional tables, such rollback cannot be done, so although the statement fails, any changes performed prior to the point of the error remain in effect.
And you aren't allowed to start a transaction in the trigger.
They should be atomic, if done in a transaction. The MySQL page on triggers has the appropriate information.
http://dev.mysql.com/doc/refman/5.0/en/triggers.html
does a transaction in a stored procedure do any locking to prevent others from updating tables?
also do i need to explicitly put in rollback logic or will the transaction automatically roll back if an error occurs because it never reaches the commit command.
Does a transaction in a stored procedure do any locking to prevent others from updating tables?
When you perform some DML on an InnoDB table, the rows affected get locked until the end of transaction (doesn't matter is it inside a stored procedure or not).
You can modify the locked rows inside the same transaction that locked it.
To explicitly lock some rows, issue:
SELECT *
FROM table
WHERE condition
FOR UPDATE
Except for commiting or rolling back the transaction, there is no other way to unlock the rows
Do i need to explicitly put in rollback logic or will the transaction automatically roll back if an error occurs because it never reaches the commit command.
You'll need to perform a rollback explicitly.