I am keeping two passwords (actually the same password as far as website human user knows,but hashed and salted using two different algorithms and salts) for my website. One is place in WebUsers table and that is where password is verified when users login at website. The other is password of an oracle user, each website user corresponds to an oracle user.
When making change password procedure, I have to change password in WebUsers table as well as in oracle, in a transaction. The problem is, the DDL statement [alter user ...] commit before performing any action. If [alter user ...] fail and in the exception handling code I rollback the transaction, the changes in the WebUsers table are not rollbacked. Is there some work around?
There is just no way to have a DML and DDL in one atomic transaction under Oracle.
In Oracle a a DDL will always explicitly result in a commit before running the DDL.
Typically in these sort of scenarios, you should execute the step that's most likely to fail first, i.e. in your case the DDL 'Alter User'.
And then run your DML , only if the DDL succeeds , but then again, there is this issue of the DML failing, and then not being able to rollback the DDL, at which point you'll simply have to run another DDL to revert the changes made by the first DDL.
The idea is that the second step is far more likely to fail than the first step.
This pattern is also used, where you've to deal with say something like JMS + JDBC , and you can't use a JTA transaction to wrap the JMS + JDBC activities in a single transcation.
Related
I am creating a simple application where I am using a Servlet and JDBC to create users.
Is there any way I can use a trigger to insert the username into another table when the Oracle user is created with:
create user xyz ......
Once this query executes successfully, it inserts the user information in the DBA_USERS table.
I want the username to also be inserted into another table. Should I add it to that other table manually through JDBC, or can I create a trigger to do it automatically?
You could use a system trigger based on the create user DDL (but not a DML trigger on the dba_users view - you can't do that anyway, but don't even think about trying to do anything based on the data dictionary). But you wouldn't really have any way for that to know if the user being created is actually an application user - you'd be assuming any user added to the DB could only be related to your application.
Since you have to take other steps anyway - such as granting roles and/or privileges, maybe adding other application security data, etc., it probably makes more sense to do the table insert manually.
It may even make more sense to put all the user-creation code into a stored (and probably packaged) procedure, and just call that over JDBC; the downside of that is that the create user and any other DDL would need to be executed from within the procedure as dynamic SQL. Any of your own table inserts would be together though, and you'd only have that single JDBC call to make.
You can also have other procedures to modify and delete users.
Something to bear in mind, however you do it, is that DDL implicitly commits. Not necessarily a problem, just something to be aware of, so you can order the steps in a recoverable way.
I am having table ABC and using in procedures with Delete action at starting and select action at end. (Delete with no where clause)
Now if a process A invokes the procedure and it is at select on table ABC, then at same time another process B invokes the procedure which reached to Delete on ABC without any where clause.
So my question is, would process A can find the data as Delete with no where clause is happening at same time.
Literally, is synchronization would be there among tables.
I'd suggest you read about Oracle multi-versioning and ACID transactions
http://docs.oracle.com/cd/E18283_01/server.112/e16508/consist.htm
https://en.wikipedia.org/?title=ACID
Things that happen in a session within a transaction are not available to another session. This continues until a commit is issued. You have your own version until a commit or rollback is issued.
Oracle starts a transaction by default unlike some other database servers. Other database servers also have their own defaults and different implementations of ACID.
I have a series of rename table ddl statements that I would like to run within a transaction. During this period, there will also be other sessions that will be running as well which might hijack the tables used for the rename above and cause a resource contention/deadlock.
Is it possible to achieve that in Oracle? Understand that each ddl statements will commit after each execution which will free up the tables for other sessions to hijack. How can I ensure that the current session that is executing the DDL statments complete successfully before other sessions can access the tables?
--LOCK TABLE a
RENAME tbl a to b
--possible contention as commit release the lock on tbl a
RENAME tbl b to c
RENAME tbl c to d
--commit
DDL statements in Oracle are each a transaction. Each DDL statement causes few or many changes in the data dictionary, like obj$. I am not sure, but looking at the major work Oracle has gone through to ensure that locking is not an issue with even the early versions of their platform, I think they found it easier to commit per DDL statement to keep the locks short in time and avoiding dead locks within a session or between sessions doing DDL. Under some circumstances, you can still feel that the Oracle kernel doesn't lock dropping and creating to many objects during production use with ORA-600 thrown at your head.
As a workaround, you can either use the datamodel versioning introduced a few years ago. I have no working experience with it since it is too restricted for my work, but you can find more on it by googling on 'Edition-based redefinition' or going to Oracle manual. It might not be available in the licensed edition of Oracle you are working on.
As a workaround, you can execute the statements during uptime. But this will generally break sessions unless the code your users are executing automatically recovers easily. Remember that each object has an ID and a name. Changing the name might not change the ID, so many pointers to the object will need to be refreshed, leading to ORA-4063 or alike. Oracle has no pause/suspend for sessions as far as I know.
I need to do a task but I have no idea how to do it.
Here is the problem:
I have about 1000 tables on a Oracle Database and many processes.
Each process does one or more SELECT on one or many tables.
Because it's almost impossible to look in the source code to find which process does which SELECT on which tables, I would like to have some kind of trigger on SELECT on every table.
The idea is that I will launch the processes one by one to be able to see which tables will query.
I know that there is no trigger on SELECT, but is there anything else?
I need to do this in a one shot, just to recover the necessary info, it will not run every day.
You could activate auditing. You can audit all SELECT with:
AUDIT SELECT TABLE;
You can specify BY SESSION so that only one record will be written to the audit trail per table accessed per session.
Your AUDIT_TRAIL parameter must be set to either DB or OS. If it is set to DB, the audit trail will be written to the SYS.AUD$ table.
Assuming that you can map a "process" in your terminology to a particular Oracle session, you could trace the Oracle session. That would show you all the SQL statements executed by that session.
You could also potentially do a SQL*Net trace from whatever the client machine is (note that the "client machine" in a three-tier environment is the application server). A SQL*Net trace tends not to be nearly as easy to work with, however.
Could in Oracle DDL (create/alter) be transactional like they are in MS SQL (started from 2005)?
DDL is not transactional in Oracle. From the 11.2 doc:
Oracle Database implicitly commits the current transaction before and after every DDL statement.
No. In Oracle DDL statements themselves are not transactional.
Running a DDL statement will implicitly commit any open transaction for that session before starting the actual work.
In addition some statements, like an alter table statement, may fail if another session has an open transaction on the object being modified or one of its dependencies. You can set a ddl_lock_timeout to specify how long you want Oracle to wait for the object to become available.
See DDL Statements for a summary of types of DDL statements and information about their behaviour regarding locks and transactions.
Oracle Database implicitly commits the current transaction before and after every DDL statement.
Just discovered this, so needs more investigation, but Oracle's create schema authorization at least allows to bundle several DDL statements in a single transaction, thus avoiding several commits, and guarantees no side-effects, i.e. a rollback, if any one of the DDL statement fails.
It is unclear whether the rollback applies to the wrapped DDL statements only, as-if the create schema started a save-point, or the outer transaction with possibly some prior DML statement.
You still cannot avoid the commit after the last wrapped DDL statement complete successfully though.