Oracle Trigger after restricted session and db startup - database

I have an Oracle db 11 that contains 3 instances. I need that event 31156 will be trace forever,
so I run this alter statment on each instance:
alter system set events '31156 trace name context forever, level 0x400';
The problem is that this parameter resets every time the db is restarted or getting into restricted mode and out of restricted mode.
I want to create 2 db triggers that will run this command, one after start up and the second after disabling restricted mode.
I created the start up trigger like that:
create trigger on_startup_trig after startup on database begin
alter system set events '31156 trace name context forever, level 0x400';
end;
so my first question is - will this trigger run on each of my instances when the db will be started or only once?
my second question is - is there a way to create a simmilar trigger for after disabling restricted session?
I disable restricted session like that:
alter system disable restricted session;

Related

View Name with # sign | not able to go inside to get describe

there is a view as above. but i cannot get inside of it. but when i write the select, it give me the data and ask for commit or rollback
My issue is that Actual cost is wrong. SO i need to correct it. but not able to go inside and see what is happening there.
Do you guys have any idea of what is this '#' sign and why it is not allow to inside?
why it ask for commit?
Oracle says that it is possible to crate table name with '#' sign. but this is not it.
I am using PL/SQL developer
Guidance ? :)
Yes, it happens when selecting from a view via a database link.
This is why: Controlling connections established by database links (https://docs.oracle.com/cd/B28359_01/server.111/b28310/ds_appdev002.htm#ADMIN12194):
When a global object name is referenced in a SQL statement or remote
procedure call, database links establish a connection to a session in
the remote database on behalf of the local user. The remote connection
and session are only created if the connection has not already been
established previously for the local user session.
The connections and sessions established to remote databases persist
for the duration of the local user's session, unless the application
or user explicitly terminates them. Note that when you issue a SELECT
statement across a database link, a transaction lock is placed on the
undo segments. To rerelease the segment, you must issue a COMMIT or
ROLLBACK statement.
As you're just selecting, it doesn't really matter whether you'll rollback or commit (I push the rollback button). After that, recreate the view so that it calculates the correct value you've mentioned.

Trigger that sends email in SQL Server

I want to send email in a trigger. I am using msdb.dbo.sp_send_dbmail for that. I have problem how to setup permissions properly.
I do not want to add DatabaseMailUserRole of msdb to the user of the database which has access to the data.
Therefore, I have created another user mailer who has DatabaseMailUserRole.
The trigger definition is:
CREATE TRIGGER MyTrigger
ON MyTable
WITH EXECUTE AS 'mailer'
AFTER INSERT
AS
BEGIN
exec msdb.dbo.sp_send_dbmail ...
END
I am getting the following error:
The EXECUTE permission was denied on the object 'sp_send_dbmail', database 'msdb', schema 'dbo'.
(When I remove the WITH EXECUTE AS 'mailer' and add DatabaseMailUserRole to the user who is accessing the database, it works correctly.)
I would recommend not to do any heavy lifting and/or time consuming tasks (like sending an e-mail) in a trigger.
The trigger gets executed in the context of the transaction that caused it to fire - and that transaction will have to wait until the trigger and all its operations are done. This is a sure fire way to kill off any performance in your system.
What I'd rather recommend is this:
inside your trigger, just make a "note" into a table that something needs to be done (like sending an e-mail; store all the relevant info that you need into that table) - and then that's all the trigger does
create a separate, stand-alone task (e.g. a scheduled job, run by the SQL Server Agent) that checks that "command" table periodically, and then actually does the action needed - like sending the e-mail, updating a large number of rows, exporting data - whatever it might be
With such a setup, you make sure your triggers stay lean and nimble and don't cause more slowdown on your system than absolutely necessary.

SQL Job Agent DB Restore fails with error #6107: Only user processes can be killed

We have an SQL Job Agent that runs in the "wee hours" to restore our local database (FooData) from a production backup.
First, the database is set to SINGLE_USER mode and any open processes are killed. Second, the database is restored.
But the 3rd step fails occasionally with Error 6107: "Only User Processes Can Be Killed"
This happens about once or twice a week at seemingly random intervals. Here is the code for step 3 where the failure occasionally occurs:
USE master;
go
exec msdb.dbo.KillSpids FooData;
go
ALTER DATABASE FooData SET MULTI_USER;
go
Does anybody have any ideas what might be occurring to cause this error? I'm thinking there might be some automated process starting up during step 3 or possibly some user trying to log in during that time? I'm not a DBA, so I'm guessing at this point, although I believe that a user should not be able to log in while the DB is in SINGLE_USER mode.
A user probably isn't logged in. The system is probably performing some task. The output of exec sp_who or sp_who2 will show what sessions are open. Any SPID below 50 is a system process, and cannot be killed with KILL. The only way to stop them is to stop the SQL Server service or issue a SHUTDOWN command (which does the same thing).
I found the answer to my problem by changing one line of code which worked like a charm.
As mentioned in the original question, the 'KillSpids" line is used in Step 1 of the job. (Along with SET SINGLE USER) The 'KillSpids' made sense in Step 1 because there may be unwanted processes still active on the database.
The 'KillSpids' line was then added again into Step 3, but it was unnecessary, and was also causing the 6107 error.
I replaced the 'KillSpids' line with the one shown below. Setting the freshly restored database to single user mode takes care of the concern that a user might try to log in before all the job steps have been completed. Here is the updated code:
USE master;
go
ALTER DATABASE [FooData] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
go
ALTER DATABASE FooData SET MULTI_USER;
go

Why does running my application create excess sessions and drop the database connection?

I have created a database application using jsp/servlets that is now hosted in a production server. But when I do some tasks with the application, the number of database sessions goes to more than 150 then the connection is lost. If I don't restart the database server I cant work with the application. I am using ORACLE 11g.
For this problem, you can do two things,
you can exceed the number of processes which can handle by the database using the following command.
alter system set sessions = 300 scope = spfile;
To do this you have to login to the database as the system user.
You can check whether all the opened database connections are closed.
The problem was the lack of proper database connection closes. When we do some repeated activities without closing database connections in each iteration. It increases the number of connections with the database and come to a maximum connections that can have according to the per-defined. To avoid this problem we can do two things,
we can increase the maximum session amount. And if you are increasing sessions parameter you should consider increasing processes and transactions parameter as well. Here is the formula you can use to determine their values.
processes=x
sessions=x*1.1+5
transactions=sessions*1.1
To do this use the bellow sql scripts
sql> alter system set processes=500 scope=both sid='';
sql> alter system set sessions=555 scope=both sid='';
sql> alter system set transactions=610 scope=both sid='*';
The other method is you can design your application to not exceed the database connections at one time more than the previously defined. Oracle automatically remove the connections that is not using currently periodically. But this gets time.

Test Before Attempting Exclusive Lock

I've written some code to upgrade a SQL Server database. Before I upgrade the database, I attain an exclusive lock via:
ALTER DATABASE Test SET SINGLE_USER WITH NO_WAIT
However, I'd like to test the database to see if the exclusive lock is possible before I run the above code. The test doesn't have to be 100% perfect, I'd just like to avoid the possibility of a timeout when attempting to gain an exclusive lock.
To that end, I've written the code below:
SELECT
*
FROM
sys.db_tran_locks
WHERE
resource_database_id = DB_ID('Test') AND
request_session_id <> ##SPID
I'm assuming that if there's 1 or more row returned, then the database must be in use. Is this true? Or is it not that simple?
UPDATE Taking #gbn's comments into account, I've decided to force rollback of existing connections using the following statement:
ALTER DATABASE Test SET SINGLE_USER WITH ROLLBACK IMMEDIATE
Before running this code, I'll give the user the an opportunity to opt out. However, I'd like the user to be able to see the list of active connections to the database - so they can make an informed decision. Which leads me onto this question.
Mainly, a DB lock is just to show it is in use. Databases don't really have many exclusive locks situations compared to code/table objects.
Single user mode is not a lock, but the number of connections allowed.
I'd wrap the ALTER DATABASE in a TRY/CATCH block because there is no guarantee the state won't change between check and ALTER DB.
However, I could be wrong or misunderstanding the question... so you'll also have to test for the exclusive lock mode on the database resource in the query above. Your code above will show you any lock, which could be someone having a blank query window open in SSMS...
Edit, based on comment
You can detect who is using it by these:
sys.dm_exec_connections
sys.dm_exec_sessions
sys.dm_exec_requests
To be honest, it's difficult to stop auto stats update or a user taking the single connection. Normally, you'd this which disconnects all other users and not bother waiting...
ALTER DATABASE MYDB SET SINGLE_USER WITH ROLLBACK IMMEDIATE
What if the database becomes busy from the time you determined that it was not in use, until the point where you try to acquire the exclusive lock?

Resources