Does MariaDB support nested transactions (not savepoints)?
I want to be able to use nested transactions in stored procedures. Currently in MySQL I am passing a parameter, "useTransaction" to each stored procedure, which controls if I start a new transaction in the body of that stored procedure.
It would more more convenient if transactions could be nested like this.
Nope. But MariaDB has ##in_transaction, which tells you if a transaction is already in progress.
No, but both MariaDB and MySQL have chained transactions:
START TRANSACTION;
[do e.g. an insert here]
COMMIT AND CHAIN;
[do e.g. another insert here]
COMMIT AND CHAIN;
[do e.g. yet another insert here]
COMMIT;
Related
I am looking to implement the equivalent of snapshot isolation with a Teradata transaction. Oracle supports this type of isolation, but Teradata does not (at least not in versions 14 or prior that I am aware of). The goal is to create a procedure that deletes a table's contents and then repopulates it all while preventing other users from reading from/writing to the table.
I came across the begin request statement which, according to my understanding, allows the optimizer to know about all the various table locks within the request.
I wrote the procedure below, but don't know how to reliably debug it as easy as I would if I were testing thread locking in a .NET application (easy to set breakpoints and monitor other threads). In Teradata, not sure if what I wrote here will properly lock mydb.destinationtable exclusively for the duration of the procedure. Is this correct?
Edit: I'll add that the procedure does work. It's just being able to properly time a SELECT while it's doing its DELETE/INSERT.
replace procedure mydb.myproc()
begin
begin request
locking mydb.destinationtable for exclusive
delete mydb.destinationtable;
locking mydb.destinationtable for exclusive
insert into mydb.destinationtable
select * from mydb.sourcetable;
end request;
end;
BEGIN REQUEST/END REQUEST creates a so-called Multi Statement Request (MSR) which is the same a submitting both requests in SQL Assistant using F9.
To see the plan run this with F9:
EXPLAIN
locking mydb.destinationtable for exclusive
delete mydb.destinationtable;
insert into mydb.destinationtable
select * from mydb.sourcetable;
or in BTEQ:
EXPLAIN
locking mydb.destinationtable for exclusive
delete mydb.destinationtable
;insert into mydb.destinationtable
select * from mydb.sourcetable;
Btw, the 2nd lock is redundant.
But. When you run Delete & InsSel as a single transaction both will be Transient Journalled. Which is much slower than seperate requests.
A more common way to do this is to use two copies of the target table and base access on Views not Tables:
-- no BEGIN/END REQUEST
insert into mydb.destinationtable_2
select * from mydb.sourcetable;
-- there's just a short dictionary lock
-- all requests against the view submitted before the replace use the old data
-- and all submitted after the new data
replace view myview as
select * from mydb.destinationtable_2;
delete from mydb.destinationtable_1;
Now your SP only needs the logic to switch between 1 & 2 (based on table [not] empty)
In my .Net webapp, I need to update two tables. I want to commit the updates only if both updates succeed. I'm new to teradata, does anyone know how to do this?
You can use Begin Transaction and End Transactions. Put the updates inside the BT ET block as shown below. If any one of the update fails, your transaction will rollback.
For Eg :
BT;
updt1;
updt2;
ET;
How can I rewrite my transaction to undo changes since the beginning whenever an error condition occurs before the end?
I see this question has already been asked and I followed the link provided in that answer. It's not clear to me what the next step is. I am hoping someone can illustrate the solution with an example applied to this transaction:
BEGIN TRANSACTION;
INSERT INTO Employee(ID, Name) VALUES(1, 'John');
...
<some failure happens here>
...
END TRANSACTION;
In this case, I would like the insert into the Employee table to be undone because a failure occurs before END TRANSACTION. How do I write rules that enforce this? This is for sqlite version 3.9.2.
Execute a ROLLBACK TRANSACTION query, or use the ON CONFLICT ROLLBACK conflict resolution on the failable queries to let SQLite roll back the transaction for you.
when looking in symfony2 at the DB Queries I have 18 queries. (I think it is a lot) I am only updating one records.
Anyway. I also saw that some of thoses queries are named 'COMMIT' and 'START TRANSACTION'. Which is not very clear what it does. Any one could explain it to me? thanks.
here an exemple of what I have with Symfony2
Jovan's link is a better read, but in layman's terms, all queries between START TRANSACION and COMMIT are treated as a whole; meaning, if one of those queries fails then they all 'rollback' and fail. START TRANSACTION simply signifies the start of the grouping, and COMMIT finishes it. It's used when you logically need all of the queries to happen.
Say for instance you want to insert a new employee, and they have to have some permissions set. You need to insert into a user table and then a user_roles table.
Now, say you don't use the above, and try running the following two inserts:
INSERT INTO user (...);
INSERT INTO user_roles (...);
What if the first query works, but the second query doesn't? You'll have a 'dangling` user without any permissions, and they'll be sitting in database limbo.
If you instead use a transaction as shown below, you can make sure that either all the queries work, or none of them work.
START TRANSACTION;
INSERT INTO user (...);
INSERT INTO user_roles (...);
COMMIT;
Because database transactions are very serious topic, instead of me trying to explain it here very briefly, I think it would be more beneficial to you to read this wiki article:
Wikipedia: Database Transactions
I am running an END TRANSACTION on my database and occasionally I get error
#1 that "cannot commit - no transaction is active"
Is there a way to determine if a transaction is active before trying a commit? I have been tracking my "BEGIN TRANSACTIONS" by hand but I feel there is a better way.
I am using the C API
You might want to check this:
http://www.sqlite.org/c3ref/get_autocommit.html
According to the page, if you are in a transaction, sqlite3_get_autocommit() will return 0.
The interface you're looking for is actually implemented in this next version of sqlite as you can see in the notes: https://sqlite.org/draft/c3ref/txn_state.html
Determine the transaction state of a database
int sqlite3_txn_state(sqlite3*,const char *zSchema);
The sqlite3_txn_state(D,S) interface returns the current transaction state of schema S in database connection D. If S is NULL, then the highest transaction state of any schema on databse connection D is returned. Transaction states are (in order of lowest to highest):
SQLITE_TXN_NONE
SQLITE_TXN_READ
SQLITE_TXN_WRITE
If the S argument to sqlite3_txn_state(D,S) is not the name of a valid schema, then -1 is returned.
That's weird. I thought sqlite was always in a transaction, either explicitly created by you or implicitly created by sqlite:
http://www.sqlite.org/lang_transaction.html
So I suppose the error means that it's not in a transaction that you initiated ... and if that's what you need to know, it seems OK for sqlite to expect you to keep up with it. Not terribly convenient of course, but I guess that's the cost of a simple API. =/
In SQLite, transactions created using BEGIN TRANSACTION ... END TRANSACTION do not nest.
For nested transactions you need to use the SAVEPOINT and RELEASE commands.
See http://www.sqlite.org/lang_transaction.html
and http://www.sqlite.org/lang_savepoint.html