Is there any way to capture SQL Server connections for when a user connects to my database until the user disconnects. For example, I want to capture login data for every user that accesses my SQL Server through Excel. Is there a trigger or DMV that will capture the time the user spent connected? I've used sysprocesses in the past and it will show me the connections and from what program, but I need it to be more like a trigger.
Checkout the auditing functions built into sql server.
Maybe you can use this to accomplish your goals (you can capture success and fail login attempts)
ADDED INFO
This webpage above is specifically re: login auditing - introduced in sql 2005
ADDED INFO PART DEUX
Read your question again, and see you want the duration not (not just the login) -- a little harder, but, see the reference for sp_trace_setevent. You should see events for login and logoff here. I've heard that capture logout is a bit more server intensive. Also, not that people do not always logout. They lose connections, crash the machine, etc. not sure how trustworthy the logout data will be. Connection pooling may also complicate you life.
Related
I've heard it said many times that the Windows Authentication is preferred over SQL Server authentication when it comes to securing SQL Server, however, this has always struck me as counterintuitive since if a user's Windows Authentication requires them to be able to modify tables, then there's no way to prevent this activity should they log in using SSMS - bypassing the application logic.
I've used server triggers in the past to prevent this but I've also had a couple scenarios where this left us unable to log on to the SQL Server. I also get that many people would argue that, for this reason, all updates to the database should be done via stored procedures - which isn't an option for us since many of our applications are COTS.
How have others handled this? Am I the only one who sees this as a problem?
I am trying to see what queries are currently running in an oracle DB. However, when I try using the table v$session it gives me an error:
What's the cause of this and what would be the correct way to get the active processes that are running?
I'm looking to get the necessary information to be able to cancel a query for a given user. Let me give an example:
1) User executes query in the application. We add in a comment so we can 'track' that query:
/* Query-ID-1283849 */ select * from mytable
2) Now, if the user clicks the "Cancel" button while the query is running (let's say the query is taking a very long time to respond), we allow the user to cancel that query, given that the user will probably NOT be a sys user but a 'normal' user with read-only privileges.
How could this be done?
At the fundamental database level, you can't kill individual queries. You kill individual sessions. I'm inferring from your question that your specific use case is inside an application, not a tool like Sql Developer or Sql Plus.
Session killing can be done by users that have special database privileges to kill sessions. If you are inside an application running multiple queries in one session, killing the session will effectively kill your application and require either a) an application restart or b) gracefully programatically handling the dropped session.
If you are using an n-tier ORM framework that handles database interactions for you, you may be in a position where killing the session won't have any affect on your application other than the currently running statement.
Another way in your app to handle isolating sessions and queries is to run a multi-threaded application. Each query spawns a new thread, and the thread can be killed without necessarily killing the session.
Basically, the short answer is you can kill a query only by killing its session. Your approach of looking at v$session is correct and necessary to find the session id for any givel sql statement, you just need to have your DBA grant your privileges to the v$session and v$sql synonyms.
Update specific to Sql Developer, based on OP's comment for clarification:
Sql Developer has an option to allow running parallel queries, taking advantage of threads and multiple connections. That setting is found at Tools > Preferences > Database > Worksheet. Regardless of the setting, when you click the query cancel button, the app is still sending a session kill request. The GUI will usually gracefully start a new session and the end user is none the wiser about it. But sometimes things don't work out and the GUI freezes or you end up with no connection and have to manually reconnect.
To add to the complexity, the behavior depends on the driver/client used by your application. OCI, thick clients, and thin clients have shown different behaviors in the past when it comes to kill requests. In fact, in Sql Developer, you have an option to force it to use OCI or a thick driver so that you can avoid certain behaviors.
I'd highly recommend getting rights to view v$session and play around with this. It's fun to learn more about how Oracle manages sessions.
I just discovered that the latest version, Oracle 18c, allows killing an individual query within a session. I'm on 12c so I have not tried this. https://docs.oracle.com/en/database/oracle/oracle-database/18/admin/managing-processes.html#GUID-7D8E5E00-515D-4338-8B86-C2044F6D2957
Relevant parts from the documentation.
5.10.5 Cancelling a SQL Statement in a Session You can cancel a SQL statement in a session using the ALTER SYSTEM CANCEL SQL statement.
Instead of terminating a session, you can cancel a high-load SQL
statement in a session. When you cancel a DML statement, the statement
is rolled back.
The following clauses are required in an ALTER SYSTEM CANCEL SQL
statement:
SID – Session ID
SERIAL – Session serial number
The following clauses are optional in an ALTER SYSTEM CANCEL SQL
statement:
INST_ID – Instance ID
SQL_ID – SQL ID of the SQL statement
You can view this information for a session by querying the GV$SESSION
view.
The following is the syntax for cancelling a SQL statement:
ALTER SYSTEM CANCEL SQL 'SID, SERIAL, #INST_ID, SQL_ID';
I have a delicate situation wherein some records in my database are inexplicably missing. Each record has a sequential number, and the number sequence skips over entire blocks. My server program also keeps a log file of all the transactions received and posted to the database, and those missing records do appear in the log, but not in the database. The gaps of missing records coincide precisely with the dates and times of the records that show in the log.
The project, still currently under development, consists of a server program (written by me in Visual Basic 2010) running on a development computer in my office. The system retrieves data from our field personnel via their iPhones (running a specialized app also developed by me). The database is located on another server in our server room.
No one but me has access to my development server, which holds the log files, but there is one other person who has full access to the server that hosts the database: our head IT guy, who has complained that he believes he should have been the developer on this project.
It's very difficult for me to believe he would sabotage my data, but so far there is no other explanation that I can see.
Anyway, enough of my whining. What I need to know is, is there a way to determine who has done what to my database?
If you are using identity for your "sequential number", and your insert statement errors out the identity value will still be incremented even though no record has been inserted. Just another possible cause for this issue outside of "tampering".
Look at the transaction log if it hasn't been truncated yet:
How to view transaction logs in SQL Server 2008
How do I view the transaction log in SQL Server 2008?
If you want to catch the changes in real time, I suggest you consider using SqlDependency. This way, when data changes, you will be alerted immediately and can check which user is using the database at the very moment (this could also be done using code).
You can use this code sample.
Coming to think about it, you can establish the same effect using a trigger and writing ti a table active users. Of course, if you are suspecting someone is tempering with data, using SqlDependency might be a better way to go with, as the data will be stored outside of the tampered database.
You can run a trace, for example a distant profiler trace, that will get all SQL queries containing the DELETE keyword. This way, nobody will be aware that queries are traced. You can also query the default trace regularly to get the last DELETE commands: Maintaining SQL Server default trace historical events for analysis and reporting
I've just started looking at a system that implements security a little differently to the norm.
They create a new SQL user for each user of the system (of which there are about 32K now). Each query is sent via a connection that is initially using the SA account (lets not get bogged down on this), then after we know who the user is, the EXECUTE AS USER is used each query.
Now that there are so many users, creating new users and switching has a noticeable performance hit and the company is looking at improving the situation.
A few points:
- SQL Code is dynamic sql (not stored procedures)
- The original idea was to alleviate the need for the developers of the company to worry about writing SQL worrying about permissions - and let another layer worry about it.
How does one try and improve the query execution time and avoid the EXECUTE AS USER code and still get the same security scrutiny?
Does SQL Server support session variables to store a user account?
It's difficult to know whether this is helpful without a bit more detail on how your application security model and how it controls and/or pools database connections. Is it a fat client, n-tier or something else?
SQL connections can support a single "session variable" using CONTEXT_INFO - a user-configurable binary(128) field which persists for the duration of the connection. This may meet your requirements, but you need to beware that if you use it to store security information it will be accessible to the end user - you should therefore probably encrypt or salt and hash any security information in the CONTEXT_INFO to prevent users tampering with their permissions; this may have performance implications.
It may not be applicable depending on your application architecture, but have you considered switching to Windows authorisation and organising permissions though Active Directory users and groups?
One of the most important databases that I administer is poorly designed. The program which uses it uses only 1 login which happens to be a System Administrator. Edits and deletes are done in place so change tracking is difficult.
Further, it lacks proper auditing functionality so I cannot tell which user edited or deleted a certain record.
I thought I might resort to using SQL triggers and output the record information along with information about the user who edited/deleted it. I can't use LoginName because the program only uses one login.
Can I export other information using a trigger such as the desktop machine name which sent the delete command?
Is there any other information that I could export that would assist me in this?
You might look at the sys.sysprocesses table (sysprocesses in SQL Server 2000 I think). It contains information that you normally see in the output of the sp_who2 stored procedure. It includes hostname, which is the computer that is connecting to SQL Server. Some of the other columns may be useful too.