How to find SPID of a executing SqlAgent job using SMO - sql-server

With SMO objects using Server.JobServer.jobs to get a list of jobs, I can find the status of each job. For those that are currently executing I would like to find the SPID it is executing on. I can also get a list of the server's processes using Server.EnumProcesses(). This gives me a list of currently active SPIDs. I want to match the two.
The best I've been able to come up with is to convert the jobid to a string and substring the jobId out of the program string in the EnumProcesses table (which, at least on my system, embeds the jobId in this description). It's really ugly for a couple of reasons not the least of which is that the Guid in the program description and the guid for jobID have their bytes switched in the first 3 pieces of the string representation. Yuck.
Is there a better way to do that using SMO?

Using SMO, not that I know of.
I have done this using T/SQL. Take the job_id value and cast it to varbinary. That should then match the value in the application name (after the "SQL Agent" part).

Use SP_who2 , in the result "Program" field you will find SQLAgent-Jobid. you will get the jobID from sysjobs from MSDB table. now you can get the sp_id of the job

Related

Finding total number of tables in union query

I am writing a code which supports different versions of Sybase ASE. I am using union queries and the problem is that different version of Sybase ASE supports different number of tables in union query. The union query is dynamic and will be formed depending on the number of database present in the server.
Is there any way in which I can find the max number of tables supported by a particular Sybase ASE? The only solution that I know right now is to fetch the version using query and pick out the version number from the result and set the number accordingly in the code. But this is not a very good solution. I tried checking if there are any tables which have stores this value but nothing came up. Can anyone suggest any solution for this?
Since that's my SAP response you've re-posted here, I'll add some more notes ...
that was a proof of concept that answered the basic question of how to get the info via T-SQL; it was assumed anyone actually looking to implement the solution would (eventually) get around to addressing the various issues re: overhead/maintenance, eg ...
setting a tracefile is going to require permissions to do it; which permissions depends on whether or not you've got granular permissions enabled (see the notes for the 'set tracefile' command in the Reference manual); you'll need to decide if/how you want to grant the permissions to other users
while it's true you cannot re-use the tracefile, you can create a proxy table for the directory where the tracefile exists, then 'delete' the tracefile from the directory, eg:
create proxy_table tracedir external directory at '/tmp'
go
delete tracedir where filename = 'my_serverlmiits'
go
if you could have multiple copies of the proxy table solution running at the same time then you'll obviously (?) need to make sure you generate a unique tracefile name for each session; while you could do this by appending ##spid to the file name, you could also add the login name (suser_name()), the kpid (select KPID from master..monProcess where SPID = ##spid), etc; you'll also want to make sure such a file doesn't exist before trying to create it (eg, delete tracedir where filename = '.....'; set tracefile ...)
your error (when selecting from the proxy table) appears to be related to your client application running in transaction isolation level 0 (which, by default, requires a unique index on the table ... not something you're going to accomplish against a proxy table pointing to an OS file); try setting your isolation level to 1, or use a client application that doesn't default to isolation level 0 (eg, that example runs fine with the basic isql command line tool)
if this solution were to be productionalized then you'll probably want to get a separate filesystem allocated so that any 'run away' tracing sessions don't fill up an important filesystem (eg, /var, /tmp, $SYBASE, etc)
also from a production/security perspective, I'd probably want to investigate the possibility of encapsulating a lot of the details in a DBA/system proc (created to execute under the permissions of the creator) so as to ensure developers can't create tracefiles in the 'wrong' directories ... and on and on and on re: control/security ...
Then again ...
If you're going to be doing this a LOT ... and you're only interested in the max number of tables in a (union) query, then it'd probably be much easier to just build a static if/then/else (or case) expression that matches your ASE version with the few possible numbers (see RobV's post).
Let's face it, how often are really, Really, REALLY going to be building a query with more than, say, 100 tables, let alone 500, 1000, more? [You really don't want to deal with trying to tune such a monster!! YIKES] Realistically speaking, I can't see any reason why you'd want to productionalize the proxy table solution just to access a single row from dbcc serverlimits when you could just implement a hard limit (eg, max of 100 tables).
And the more I think about it, as a DBA I'm going to do whatever I can to make sure your application can't create some monster, multi-hundred table query that ends up bogging down my dataserver simply because the developer couldn't come up with a more efficient solution. [And heaven forbid this type of application gets rolled out to the general user community, ie, I'd have to deal with dozens/hundreds of copies of this monster running in my dataserver?!?!?!]
You can get such limits by running 'dbcc serverlimits' (enable traceflag 3604 first).
Up until version 15.7, the maximum was 256.
In 16.0, this was raised to 512.
In 16.0 SP01, this was raised again to 1023.
I suggest you open a case/ticket with SAP support to know if there is any system tables that store this information. If there is none, I would implement the tedious solution you mentionned and will monitor the following error in the ASE15.7 logs:
CR 805525 -- If you exceed the number of tables in a UNION query you can get a signal 11 in ord_getrowbounds instead of an error message.
This is the answer that I got from the SAP community
-- enable trace file for your spid
set tracefile '/tmp/my_serverlimits' for ##spid
go
-- dump dbcc serverlimits output to your tracefile
dbcc serverlimits
go
-- turn off tracing
set tracefile off for ##spid
go
-- enable external file access:
sp_configure 'enable file access',1
go
-- create proxy table pointing at the trace file
create proxy_table dbcc_serverlimits external file at '/tmp/my_serverlimits'
go
-- find our column name ('record' of type varchar(255) in this case)
sp_help dbcc_serverlimits
go
-- extract the desired row; store the 'record' value in a #variable
-- and parse for the desired info ...
select * from dbcc_serverlimits where lower(record) like '%union%'
go
record
------------------------------------------------------------------------
Max number of user tables overall in a statement using UNIONs : 512
There are some problems with this approach though. First issue is setting trace file. I am going to use this code mostly daily and in Sybase, I think we can't delete or overwrite a trace file. Second is regarding the proxy table. Proxy table will have to be deleted, but this can be taken care with the following code
IF
exists (select 1 from
sysobjects where type = 'U' and name = 'dbcc_serverlimits')
begin
drop table
dbcc_serverlimits
end
go
Final problem comes when a select query is made from dbcc_serverlimits table. It throws the following error
Could not execute statement. The optimizer could not find a unique
index which it could use to scan table 'dbo.dbcc_serverlimits' for
cursor 'jconnect_implicit_26'. SQLCODE=311 Server=************,
Severity Level=16, State=2, Transaction State=1, Line=1 Line 24
select * from dbcc_serverlimits
All this command will have to be written in procedure (that is what I am thinking). Any more elegant solution?

Reading from the sysaudits table - Sybase ASE 15.7

I am currently trying to collect the audit logs from the Sybase ASE 15.7 sysaudits table. A SIEM will be using a query to read the audit logs.
Since the sysaudits table can be read by users with SSO role , we had to find an alternative since we cannot give the privilege to the SIEM. Our DBA tried to create a view for this purpose but since the account used by the SIEM is not having a SSO role it failed.
So the DBA proposed we create another table with the same structure (event, eventmod, spid, eventtime, sequence, suid, dbid, objid, xactid, loginname, dbname, objname, objowner, extrainfo, nodeid) and he would write a script that would read from the sysaudits table and write to this new table every 5 minutes.
So we went ahead with the solution, however I ran across a problem which is why I need help
The SIEM solution will read using a query provided by the DBA, however the SIEM solution needs a unique column to keep track of which record it last read. I noticed there is no such unique column in sysaudits. Moreover, I noticed certain commands broken into multiple entries and to keep track of them the sequence ID is used.
I was thinking if I should add another auto incrementing column ID.
That will help in keeping track of the audit logs.
For the sequence ID and commands broken in multiple entries, I was
thinking perhaps to use a script which reads from the sysaudits and
when it encounters a command broken in multiple entries, it could
merge it as one entry and write it into our table rather the original
multiple entries with sequence numbers.
How should I frame the query for this? Or is there a better way of going about this?
Also, I noticed we only get 92 in the event column event though sybase specified we can get different values for the event field. Am i supposed to get the other values also?
Thanks in advance

How to get sql_id in OCI

Is there a way to get the sql_id/child number/plan hash after calling OCIStmtExecute()? I can't see it in OCIAttrGet().
NOTE: As a regular user who can't see v$session - if I can it's as simple as executing select prev_sql_id, prev_child_number from v$session where sid=sys_context('USERENV', 'SID')
Thanks!
There is no means to get the sql_id or the plan_hash_value with oci or sys_context. However it might be a good idea to file an enhancement request with oracle support to add that feature.
There is the possibility to trace all sql statements of a session with the following statement:
alter session set events '10046 trace name context forever, level 12'
Depending on the trace level more or less trace is generated (Level 4 and 8 create less information). To turn off the tracing execute
alter session set events '10046 trace name context off'
The other option is to create a function to compute the sql_id yourself
Use the sql text and calculate a 128bit md5
The lower 64 bit are the sql_id (and if you are interested the lower 32 bits are the plan hash)
Of course this is error prone as oracle might change the mechanism to calculate the sql_id in the future.
The following query is supposed to work but only if it is the very next statement execution following the one that you wish to identify.
select prev_sql_id, prev_child_number
from v$session
where sid = sys_context('userenv','sid')
And it does work...most of the time. My customer wrote a PL/SQL application for Oracle 12c and placed the above query in the part of the code that executes the application query. He showed me output that shows that it sometimes returns the wrong value for prev_child_number. I watched and it is indeed failing to always return the correct data. Over 99 distinct statement executions it returned the wrong prev_child_number 6 times.
I am in the process of looking for existing bugs that cause this query to return the wrong data and haven't found any yet. I may have to log a new SR with Oracle support.

Date of last login or read operation on a SQL Server database?

Lets say I have a SQL Server with 100 databases on it. How can I find out which ones are actually being used?
(without turning them all off and waiting for the complaints to come in)
So 'have been accessed in the last week' or something like that.
I've tried the data file dates but they don't seem to represent that and databases do not seem to have a property that reflects this either.
This SQL query was useful for me
select max (login_time)as last_login_time, login_name from sys.dm_exec_sessions
group by login_name;
Look at sys.dm_db_index_usage_stats. The columns last_user_seek/last_user_scan/last_user_lookup/last_user_update represent the last time the respective index (heap or b-treee) was used. These values reset after server restart, so you must check them after the server was up an running for a sufficient time.
You might be able to get this information by using some of the system views related to performance.
http://technet.microsoft.com/en-us/library/ms187743.aspx

Sql Server 2005 SSIS/Agent - Query status of a job

Is there a way to query the current status (executing, idle, etc) and the last result (successfull, failed, etc), and the last run time for a specific job name? The end result I am looking for is being able to display this information in an internal web application for various SSIS packages.
You should be able to find this information inMSDB - there are tables sysjobs, sysjobhistory and sysjobsteps which give the information that you are looking for
exec msdb.dbo.sp_help_job #job_name = 'TheJobName'
gives the information I want. So then I can just use a SqlDataReader to get the information. Note that this stored procedure returns multiple result sets.
The micrsoft documentation on this store procedure is
http://msdn.microsoft.com/en-us/library/ms186722(SQL.90).aspx
Another solution I have used is to update a reference table with the current status. It's quick and easy and usually very easy to retrieve the values you need.
For example, as soon as a package kicks off, insert a record with date and time, package name, etc.

Resources