Automatically drop a temporary table when the transaction is over - mysql

I need to create a temporary table and perform a few SELECTs on it. After that I won't need that temp table. But since I'm using a connection pool, the temp table will stay there and will even interfere with the next transaction that happens to acquire the same connection.
My question is, is there a way to automatically clean-up the table when my current transaction is over?
Obviously, I could do that manually, but in order to do it properly, the code won't be that simple:
<START TX>
DROP TEMPORARY TABLE IF EXISTS some_tt;
CREATE TEMPORARY TABLE some_tt AS ...;
...
<use some_tt here>
...
DROP TEMPORARY TABLE IF EXISTS some_tt;
<END TX>
In order to release resources, we should drop the table as soon as we don't need it anymore (before the tx ends). But since we cannot guarantee the drop will happen & succeed, I believe we should also execute a drop right before the CREATE TEMPORARY TABLE statement, just in case.

A TEMPORARY table is visible only within the current session, and is dropped automatically when the session is closed. However, temporary tables are not affected by transactions and are not deleted when a transaction ends or rollbacks. In addition, the temporary table is visible to parallel transactions within the session.

Related

How to rename two tables in one atomic operation in MySQL

I need to rename two tables in one atomic operation so that user will never be able to see the database in its intermediate state.
I'm using MySQL and noticed that this case is perfectly described in the documentation:
13.3.3 Statements That Cause an Implicit Commit
The statements listed in this section (and any synonyms for them)
implicitly end any transaction active in the current session, as if
you had done a COMMIT before executing the statement
[...]
Data definition language (DDL) statements that define or modify
database objects. ALTER DATABASE ... UPGRADE DATA DIRECTORY NAME,
ALTER EVENT, ALTER PROCEDURE, ALTER SERVER, ALTER TABLE, ALTER VIEW,
CREATE DATABASE, CREATE EVENT, CREATE INDEX, CREATE PROCEDURE, CREATE
SERVER, CREATE TABLE, CREATE TRIGGER, CREATE VIEW, DROP DATABASE, DROP
EVENT, DROP INDEX, DROP PROCEDURE, DROP SERVER, DROP TABLE, DROP
TRIGGER, DROP VIEW, INSTALL PLUGIN (as of MySQL 5.7.6), RENAME TABLE,
TRUNCATE TABLE, UNINSTALL PLUGIN (as of MySQL 5.7.6).
But maybe there's some kind of workaround or something like this?
My situation looks like this:
I have a current data set in the table named current
I gathered a new data set in the table named next
I need to rename the current table to the current_%current_date_time% and the next table to the current in one atomic operation
Well, easy...
RENAME TABLE current TO current_20151221, next TO current;
as is stated in the manual. There it says that it's an atomic operation. Just to clear this up, implicit commits have nothing to do with it. That's a different story. That just says, that those statements end an open transaction.

How to rollback all statements inside a MySQL Transaction?

I need to update a specific column of a table (bigtable) containing ids of another table (FK constraint to oldsmalltable) to point to ids on another table (FK constraint to newsmalltable). Basically this is what I am doing:
DELIMITER //
CREATE PROCEDURE updatebigtable ()
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION, SQLWARNING ROLLBACK;
START TRANSACTION;
ALTER TABLE bigtable DROP FOREIGN KEY bigtable_ibfk_1,
MODIFY smalltable_id SMALLINT ;
UPDATE bigtable SET smalltable_id=CASE smalltable_id
WHEN 1 THEN 1592
WHEN 2 THEN 1593
WHEN 3 THEN 1602
...
ELSE 0
END;
ALTER TABLE bigtable ADD CONSTRAINT bigtable_ibfk_1
FOREIGN KEY(smalltable_id) REFERENCES newsmalltable(id);
COMMIT;
END//
DELIMITER ;
CALL updatebigtable();
DROP PROCEDURE updatebigtable;
I need to ensure that if by some reason the new Foreign Key constraint fails (e.g. with columns with different types, the error would occur on the last alter table statement), the UPDATE and the first ALTER TABLE should be rolled back as well, i.e. they should remain as they were initially.
According to MySQL documentation, by using START TRANSACTION the autocommit mode is disabled for that transaction, which will not allow:
that as soon as you execute a statement that updates (modifies) a table, MySQL stores the update on disk to make it permanent.
I only found this question as minimally related to mine:
How can I use transactions in my MySQL stored procedure?
If that error I mentioned occurs inside the transaction, the previous statements were already executed and the updates were "permanently done on disk"...
I also tried to place SET autocommit=0; before creating the procedure but the behavior is still the same... Am I missing something? Or is this the expected behavior of a MySQL transaction rollback?
If it makes any difference, I am using MySQL v.5.6.17.
ALTER TABLE statements always cause an implicit commit (section 13.3.3 from MySQL docs, thanks wchiquito), which means that even if they're inside a START TRANSACTION; ... COMMIT; block, there will be as many commits as the number of alters done inside that block.
Locking the table is not an option as well since (from problems with ALTER TABLE):
If you use ALTER TABLE on a transactional table or if you are using Windows, ALTER TABLE unlocks the table if you had done a LOCK TABLE on it. This is done because InnoDB and these operating systems cannot drop a table that is in use.
The only option left for avoiding unwanted reads/writes while the alter and update statements are being executed is emulating all the steps of an ALTER TABLE:
Create a new table named A-xxx with the requested structural changes.
Copy all rows from the original table to A-xxx.
Rename the original table to B-xxx.
Rename A-xxx to your original table name.
Delete B-xxx.
This way the updates can be done in the new table (after step 2) and the only time the bigtable is unavailable is while doing step 3 and 4 (renaming).
Use a TRY CATCH block
BEGIN TRAN before BEGIN TRY and ROLLBACK TRAN inside CATCH block

Mysql temp tables are dropped between executions

I want be able to debug easily my scripts in Mysql, like in MSSQL (run a chunk of the script then verify the tables and so on), but the temporary tables are not persisted on the server.
For example :
CREATE temporary table a(i int);
INSERT INTO a VALUE (1);
SELECT * FROM a;
If I run the whole script it returns me the right result, but if I run it statement by statement on the insert I get the following error:
SQL.sql: Error (2,13): Table 'test.a' doesn't exist
I suppose this is a server configuration problem.
Temporary tables are dropped when the transaction is over.
from dev.mysql:
Temporary Tables:
You can use the TEMPORARY keyword when creating a
table. A TEMPORARY table is visible only to the current connection,
and is dropped automatically when the connection is closed. This means
that two different connections can use the same temporary table name
without conflicting with each other or with an existing non-TEMPORARY
table of the same name. (The existing table is hidden until the
temporary table is dropped.) To create temporary tables, you must have
the CREATE TEMPORARY TABLES privilege.
Note CREATE TABLE does not automatically commit the current active
transaction if you use the TEMPORARY keyword.
So if you run all these sql in deferent transactions you temporary table wont exist when you run the insert statement.
If these executions are executed in diferent transactions depend on what interface you use. Thats wy if you "run the whole script it returns me the right result" because its all in the same transaction.
You can try to force it to run on the same transaction with:
START TRANSACTION;
<SQL QUERYS>
COMMIT;
anyway i recomend you MySQL Workbench as interface.
my best regards, i hope this help you.

Alternative for a MySQL temporary table in Oracle

I noticed that the concept of temporary tables in these two systems is different, and I have a musing.. I have the following scenario in MySQL:
Drop temporary table 'a' if exists
Create temporary table 'a'
Populate it with data through a stored procedure
Use the data in another stored procedure
How can I implement the same scenario in Oracle? Can I (in one procedure preferable) create a temporary table, populate it, and insert data in another (non-temporary) table?
I think that I can use a (global) temporary table which truncates on commit, and avoid steps 1&2, but I need someone else's opinion too.
In Oracle, you very rarely need a temporary table in the first place. You commonly need temporary tables in other databases because those databases do not implement multi-version read consistency and there is the potential that someone reading data from the table would be blocked while your procedure runs or that your procedure would do a dirty read if it didn't save off the data to a separate structure. You don't need global temporary tables in Oracle for either of these reasons because readers don't block writers and dirty reads are not possible.
If you just need a temporary place to store data while you perform PL/SQL computations, PL/SQL collections are more commonly used than temporary tables in Oracle. This way, you're not pushing data back and forth from the PL/SQL engine to the SQL engine and back to the PL/SQL engine.
CREATE PROCEDURE do_some_processing
AS
TYPE emp_collection_typ IS TABLE OF emp%rowtype;
l_emps emp_collection_type;
CURSOR emp_cur
IS SELECT *
FROM emp;
BEGIN
OPEN emp_cur;
LOOP
FETCH emp_cur
BULK COLLECT INTO l_emps
LIMIT 100;
EXIT WHEN l_emps.count = 0;
FOR i IN 1 .. l_emps.count
LOOP
<<do some complicated processing>>
END LOOP;
END LOOP;
END;
You can create a global temporary table (outside of the procedure) and use the global temporary table inside your procedure just as you would use any other table. So you can continue to use temporary tables if you so desire. But I can count on one hand the number of times I really needed a temporary table in Oracle.
You are right, temporary tables will work work you.
If you decide stick with regular tables you may want to use the advice #Johan gave, along with
ALTER TABLE <table name> NOLOGGING;
to make this perform a bit faster.
I see no problem in the scheme your are using.
Note that it doesn't have to be a temp-table, you can use a sort of kind of memory table as well.
Do this by creating a table as usual, then do
ALTER TABLE <table_name> CACHE;
This will prioritize the table for storage in memory.
As long as you fill and empty the table in short order you don't need to do step 1 & 2.
Remember the cache modifier is just a hint. The table still ages in the cache and will be pushed out of memory eventually.
Just do:
Populate cache-table with data through a stored procedure
Use the data in another stored procedure, but don't wait to long.
2a. Clear the data in the cache table.
In your MySQL version, I didn't see a step 5 to drop the table a. So, if you want or don't mind having the data in the table persist you could also use a materialized view and simply refresh on demand. With a materialized view you do not need to manage any INSERT statements, just include the SQL:
CREATE MATERIALIZED VIEW my_mv
NOCACHE -- NOCACHE/CACHE: Optional, cache places the table in the most recently used part of the LRU blocks
BUILD IMMEDIATE -- BUILD DEFERRED or BUILD IMMEDIATE
REFRESH ON DEMAND
WITH PRIMARY KEY -- Optional: creates PK column
AS
SELECT *
FROM ....;
Then in your other stored procedure, call:
BEGIN
dbms_mview.refresh ('my_mv', 'c'); -- 'c' = Complete
END;
That said, a global temporary table will work as well, but you manage the insert and exceptions.

Is MySQL Temporary table a shared resource?

I have a MySQL stored procedure that uses a temporary table. Assume that my table name is 'temp' and I use it to store some middle data. It will create at the beginning of procedure, and will drop at the end.
CREATE PROCEDURE p()
BEGIN
CREATE TEMPORARY TABLE \`temp\`(...);
INSERT INTO \`temp\` VALUES(...);
DROP TEMPORARY TABLE \`temp\`;
END;
The problem is that this stored procedure may be used by different users concurrently, so I want to know if this can cause any problems (i.e. any conflict in inserted data in temp table). In other word is temp table a shared resource within different calls to the same SP?
No, a temp table is limited to the scope of your database connection. You can use the temp table in subsequent calls to the procedure during the same database connection, but other connections cannot access it. They can create a table by the same name, but each temp table will be independent. Temp tables go away when you close your connection.
Temporary table is visible only for current session.
So if you have several simultaneuous sessions - each one will have its own independent temporary table with the same name.
Documentation: http://dev.mysql.com/doc/refman/5.1/en/create-table.html, ctrl+f for "You can use the TEMPORARY"