Redshift VACUUM cannot run inside a transaction block on SQLWorkbenchJ - vacuum

I have got a:
VACUUM cannot run inside a transaction block
error on SQLWorkbenchJ in Redshift, but I already commit all transactions before this.

You don't need to change the connection profile, you can change the autocommit property inside your SQL script "on-the-fly" with set autocommit
set autocommit on;
vacuum;
set autocommit off;
You can also toggle the current autocommit state through the menu "SQL -> Autocommit"

For me this worked.
END TRANSACTION;
VACCUM <TABLENAME>;

turning autocommit on and off seems like a hacky solution particularly if you have a long script punctuated with commits and vacuums (ie lots of very large temp tables). Instead, try (in one line). Also, many are reporting redshift does not like the syntax. Instead,
COMMIT;VACUUM;COMMIT;
The problem is that vacuum not only wants to be the first command in a transaction block, it wants the block to be explicitly committed after.

Related

Select * from table#dblink in PL/SQL Developer

When I run query select * from table#dblink in PL/SQL Developer,transaction commit/rollback icons are activated, but then if I use Fetch last page these icons are disabled. Why is this happening?
Querying over a db_link flips the 'we have a transaction' switch in the data dictionary
In most tools, you'll get a prompt for COMMIT or an indicator of an open transaction whenever you query against a DB_LINK.
That's because you're doing 'something' that's not clear to us in a different database. Your 'SELECT' could have side effects which require a COMMIT/ROLLBACK, or as Tom would say
'If you are distributed, you would want to commit to finish off anything that was implicitly started on the remote site.'
I think that PL/SQL is trying to remove useless transactions to help avoid session errors. It seems that whenever you press the "Fetch last page" button, PL/SQL Developer runs commit write batch if the statement contains a database link, if there are no transactions currently open in the session, and if the statement does not include FOR UPDATE.
Those are a lot of weird conditions, but they seem to ensure that the program won't commit when it shouldn't. I assume PL/SQL Developer is using commit write batch to use less resources than a normal commit. That guess is based on the number returned by this query increasing when I hit the button. (There's another statistic for user commits, and that number does not increase.)
select value
from v$mystat
join v$statname on v$mystat.statistic# = v$statname.statistic#
where lower(display_name) = 'commit batch performed';
This behavior is a little odd, but it could help prevent some errors in the session. For example, if you later try to run alter session enable parallel dml the session would throw the error ORA-12841: Cannot alter the session parallel DML state within a transaction. By committing the (worthless) transaction, you avoid some of those errors.

alter table constraint on unlock oracle

I am trying to write a script to be executed by a client who has no real knowledge of pl/sql,
I do a bunch of transactions in PL/sql to clean up their landscape and then have to add in some constraints to keep this from happening again, I commit automatically after the cleaning, and would like to finish my PL block with adding these constraints
only issue is I have no guarantee that the tables will not be locked when trying to add constraints to them, is there a wait until unlock type of command in oracle?
thank you, new to oracle and cannot seem to find this, I have combed through a bit of API but am at the point of time sensitivity and is proving very difficult to find when i think it seems like it would be a pretty regular issue with DB management
in your pl/sql block before execute any DDL you should call via execute immedaite :
LOCK TABLE <table_name> IN EXCLUSIVE MODE WAIT <n>;
where is number of seconds to wait.
But bear in mind even if you get lock after your first ddl it will be released because DDL commits automatically. So there is no way to guarantee that list of DDL commands will be executed one-by-one as in one transaction.
The command would be:
LOCK TABLE tab IN EXCLUSIVE MODE;
This will wait indefinitely if there is another session with a similar lock (which there should not be).
You can lock a table explicitly (with "WAIT") prior to a DDL, but that won't necessarily solve all of your problems if you are worried about another session holding an exclusive lock. Sounds more like you may have experienced an ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired due to a DML transaction in another session. This will eventually finish, so issuing the above lock command prior to ALTER TABLE will help you here. Just be aware that if there is a hung session elsewhere the LOCK TABLE command can wait indefinitely unless you have set a timeout.
So lets do an example:
In session A I start a transaction on tab
SQL> INSERT INTO tab VALUES(...);
In session B I attempt to add a constraint to the table.
SQL> alter table tab add constraint uk_name unique(name);
alter table tab add constraint uk_name unique(name)
*
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expire
So I'd have to try again. But instead if you precede your DDL with a LOCK ... EXCLUSIVE (WAIT)
SQL> lock table tab in exclusive mode;
-- indefinite period while the session A transaction blocks session B
Then session A commits or rolls back
SQL> commit;
Session B immediately continues when we see the lock command return Table(s) locked
Table(s) Locked.
SQL> alter table tab add constraint uk_name unique(name);
Table altered. (**comment Lock is released by the implicit commit issued the DDL statement)
SQL>
Since the DDL statement releases the lock, each DDL will need to be preceded with a fresh LOCK statement. If you want to use this, I recommend adding a timeout (as suggested in comments by Justin). Lets wait up to a minute before giving up.
SQL> lock table tab in exclusive mode WAIT 60;
Although if this is an unattended script on a busy database, I'd probably go with something more than 60 seconds. Just log everything to a spool file, and check the log later for errors.
Anything more than this sort of maintenance probably requires that you quiesce your database first, else just deal with the contention on a case by case basis.

What can i do in Oracle in order to preserve the savepoint if internal commit occurs?

background:
i'm doing some Oracle plsql refactoring; The first think that i want to accomplish is to have unit test for the principal components.
For this i'm using ruby with the gem plsq-spec https://github.com/rsim/ruby-plsql-spec
In order to execute the tests several times, i'm using Oracle Savepoints after open the database conection, and doing a rollback to the savepoint before close the connection
Problem:
Some test can't be executed more than one time, because some procedures had internal commits.
What can i do in Oracle in order to preserve the savepoint if internal commit/rollback occurs?
With this information in the note apparently what I want is impossible
http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/savepoint_statement.htm
A simple rollback or commit erases all savepoints. When you roll back
to a savepoint, any savepoints marked after that savepoint are erased.
The savepoint to which you roll back remains.
so, the only solutions are?:
modify the procedures
erase all data before execute the tests?
tks
The Flashback feature may help you here, as you can restore the database or individual tables to their state as-of a previous point in time.
http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_9012.htm

JDBC connection default autoCommit behavior

I'm working with JDBC to connect to Oracle. I tested connection.setAutoCommit(false) vs connection.setAutoCommit(true) and the results were as expected.
While by default connection is supposed to work as if autoCommit(true) [correct me if I'm wrong], but none of the records are being inserted till connection.commit() was called. Any advice regarding default behaviour?
String insert = "INSERT INTO MONITOR (number, name,value) VALUES (?,?,?)";
conn = connection; //connection details avoided
preparedStmtInsert = conn.prepareStatement(insert);
preparedStmtInsert.execute();
conn.commit();
From Oracle JDBC documentation:
When a connection is created, it is in auto-commit mode. This means
that each individual SQL statement is treated as a transaction and is
automatically committed right after it is executed. (To be more
precise, the default is for a SQL statement to be committed when it is
completed, not when it is executed. A statement is completed when all
of its result sets and update counts have been retrieved. In almost
all cases, however, a statement is completed, and therefore committed,
right after it is executed.)
The other thing is - you ommitted connection creation details, so I'm just guessing - if you are using some frameworks, or acquiring a connection from a datasource or connection pool, the autocommit may be turned off by those frameworks/pools/datasources - the solution is to never trust in default settings ;-)

Screwed up table in oracle

I have to admit that I just, well, screwed the pooch on a production database. When running an update query in SQL Developer, I did not realize that only a portion of the query was highlighted. If you have any experience with SQL Developer, this means that SQL Developer will only execute that sub-section of a query -- in this case, apparently, "UPDATE <table> SET <column>=<value>" was highlighted...
This means that the query became, "UPDATE <table> SET <column>=<value>". And yes, commit has been pressed.
Is there any way, besides restoring from backup, that this information can be retrieved, or is it just screwed now?
On Oracle you have the magical flashback query if your database is 9i or higher and your undo is not too old. Something like:
SELECT ...
FROM <table>
AS OF TIMESTAMP TO_TIMESTAMP('12-FEB-2010 10.55.00.000000');
If the query returns ORA-01555 Snapshot Too Old it means that the undo_retention value of your database configuration is not high enough for the recovery...
Was an undo segment created for the database? If so, you can roll back what you just did—if there was enough space in it.
If you don't have implicit transaction commit turned on and you still have that same connection open you could rollback your last transaction. If not restore from backup is the only other option I can think of.

Resources