This is my first foray into the world of StackOverflow, so hopefully I provide you with enough information here.
I'm an intern at my company and the boss has assigned me the task of investigating whether or not System Center Operations Manager (SCOM) can monitor for a SQL Server stack dump. Is this possible?
I was thinking of using a query to raise some sort of event in the Windows Application log. Then I could have SCOM monitor the Windows App log for stack dumps and then raise an alarm. Here is the query:
--To view SQL Server error logs in SQL Server 2005 / 2008 / 2008R2
DECLARE #HOURS INT
SET #HOURS = 24
CREATE TABLE #ErrorLog
(LogDate DateTime, ProcessInfo Varchar(50),
[Text] Varchar(4000))
INSERT INTO #ErrorLog
EXEC sp_readerrorlog
DELETE FROM #ErrorLog
WHERE LogDate < CAST(DATEADD(HH,-#HOURS,
GETDATE()) AS VARCHAR(23))
SELECT * FROM #ErrorLog
DROP TABLE #ErrorLog
I know this query won't do what I want it to, but maybe it's a starting point.
Related
Facing a deadlock in SQL server database and can see deadlock entry in SQL logs. How the log entries can be used to find the reason for this deadlock?
Deadlock information is captured by the system_health Extended Events trace by default. No need to turn on additional trace flags.
Information from the xml_deadlock event can be viewed from SSMS Object Explorer (Management-->Extended Events-->Sessions--system_health) or with T-SQL. Below is an example query to get the deadlock xml from the file target. You can also save the deadlock xml to a file with an xdl extension and open the file in SSMS for a graphical view of the deadlock.
--get xml_deadlock_report from system_health session file target
WITH
--get full path to current system_health trace file
CurrentSystemHealthTraceFile AS (
SELECT CAST(target_data AS xml).value('(/EventFileTarget/File/#name)[1]', 'varchar(255)') AS FileName
FROM sys.dm_xe_session_targets
WHERE
target_name = 'event_file'
AND CAST(target_data AS xml).value('(/EventFileTarget/File/#name)[1]', 'varchar(255)') LIKE '%\system[_]health%'
)
--get trace folder name and add base name of system_health trace file with wildcard
, BaseSystemHealthFileName AS (
SELECT
REVERSE(SUBSTRING(REVERSE(FileName), CHARINDEX(N'\', REVERSE(FileName)), 255)) + N'system_health*.xel' AS FileNamePattern
FROM CurrentSystemHealthTraceFile
)
--get xml_deadlock_report events from all system_health trace files
, DeadLockReports AS (
SELECT CAST(event_data AS xml) AS event_data
FROM BaseSystemHealthFileName
CROSS APPLY sys.fn_xe_file_target_read_file ( FileNamePattern, NULL, NULL, NULL) AS xed
WHERE xed.object_name like 'xml_deadlock_report'
)
--display 10 most recent deadlocks
SELECT TOP 10
DATEADD(hour, DATEDIFF(hour, SYSUTCDATETIME(), SYSDATETIME()), event_data.value('(/event/#timestamp)[1]', 'datetime2')) AS LocalTime
, event_data AS DeadlockReport
FROM DeadLockReports
ORDER BY LocalTime ASC;
Deadlock information can be captured in the SQL Server Error Log or by using Profiler / Server Side Trace.
1204 - this provides information about the nodes involved in the
deadlock
1222 - returns deadlock information in an XML format
You can turn on each of these separately or turn them on together.
To turn these on you can issue the following commands in a query window or you can add these as startup parameters. If these are turned on from a query window, the next time SQL Server starts these trace flags will not be active, so if you always want to capture this data the startup parameters is the best option.
DBCC TRACEON (1204, -1)
DBCC TRACEON (1222, -1)
Please refer to the following Links for more details
Redgate
MS SQL Tips
This code will display the error log which contains the query that creates the deadlock.
IF OBJECT_ID('tempdb.dbo.ErrorLog') IS Not Null
BEGIN
DROP TABLE tempdb.dbo.ErrorLog
END
CREATE TABLE tempdb.dbo.ErrorLog
(Id int IDENTITY (1, 1) NOT NULL,
logdate DATETIME, procInfo VARCHAR(10),
ERRORLOG VARCHAR(MAX))
-- insert the actual data from the Error log into our newly created table.
INSERT INTO tempdb.dbo.ErrorLog
EXEC master.dbo.sp_readerrorlog
declare #sql nvarchar(max)
set #sql='select logdate, procInfo, ERRORLOG from tempdb.dbo.ErrorLog
where Id >= (select top 1 id from tempdb.dbo.ErrorLog WHERE ERRORLOG Like
''%deadlock-list%'' order by id desc)'
select #SQL
I'm trying to create historic data for my company; previously i asked how to copy a table with a timestamp into the same mssql database. realistically, it dawned on me that what i really need to do is the following
1) log onto my local mssql box
2) run a query of a view (select * from view_whatever)
3) copy the results of the query and add a timestamp into another database, hosted using azure SQL
if i were doing this from the same database to another table, i'd something like this:
DECLARE #copyDate DATETIME2 = CURRENT_TIMESTAMP
INSERT INTO Hst_Opportunities
SELECT OppName, Oppvalue, #copyDate AS copyDate
FROM dbo.opportunities
the from part is what im struggling with - how do i copy cross server and database when the source database is MSSQL and the target is Azure SQL?
Based on my test, it appears you could create a linked server on your local box and insert the data using four part name:
EXEC master.dbo.sp_addlinkedserver #server = N'SQLAZURE', #srvproduct=N'sqlazure', #provider=N'SQLNCLI', #datasrc=N'NAME.database.windows.net', #catalog=N'TestDb'
EXEC master.dbo.sp_addlinkedsrvlogin #rmtsrvname=N'SQLAZURE',#useself=N'False',#locallogin=NULL,#rmtuser=N'USERNAME',#rmtpassword='Password'
GO
DECLARE #copyDate DATETIME = CURRENT_TIMESTAMP;
INSERT INTO [SQLAZURE].[TestDb].[Schema].[Table]
SELECT TOP (10)
[Column1]
,[Column2]
,#copyDate AS copyDate
FROM [Localdb].[Schema].[View];
I've used the SQL Profiler to generate a trace file, and tuning advisor to take that trace file and provide some recommendations on db updates.
However, the SQL Profiler doesn't seem to track the queries when running against a Reporting Server, the profiler doesn't seem to be capturing any of the queries. I'm logging the defaults (SQL:BatchCompleted and Starting, RPC:completed, and Sessions - Existing Connections)
What events should I be capturing in SQL Profiler in order to run the tuning advisor?
Update:
The BatchStarting even is capturing some SQL; however it's always something to do with the event or notifications table :
declare #BatchID uniqueidentifier
set #BatchID = NEWID()
UPDATE [Event] WITH (TABLOCKX)
SET [BatchID] = #BatchID,
[ProcessStart] = GETUTCDATE(),
[ProcessHeartbeat] = GETUTCDATE()
FROM (
SELECT TOP 8 [EventID] FROM [Event] WITH (TABLOCKX) WHERE [ProcessStart] is NULL ORDER BY [TimeEntered]
) AS t1
WHERE [Event].[EventID] = t1.[EventID]
select top 8
E.[EventID],
E.[EventType],
E.[EventData]
from
[Event] E WITH (TABLOCKX)
where
[BatchID] = #BatchID
ORDER BY [TimeEntered]
Here's what was happening, and how to work around it.
It appears that Reporting Server caches data in a temp database. Since most of our reports all used a common view, all of that data was being retrieved from cache.
After selected "Show All Events", under "Stored Procedures" I selected CacheHit, CacheInert, CacheMiss, Completed, StmtCompleted, and StmtStarting.
There was then enough information in the trace file for the profiler to evaluate and make recommendations.
I'd like if its possible to work out from inside sql server how long sql server has been running.
Would like to use this in conjunction with one of the DMV's for unused indexes, but the counters are re-set every time sql server loads, so I'd like to know how useful they're going to be.
SELECT
login_time
FROM
sys.dm_exec_sessions
WHERE
session_id = 1
will give you a datetime for when the server was started.
To get it programmatically, you can run this script. It checks the creation time of your tempdb, since tempdb gets reinitialized every time Sql Server is started.
SELECT create_date
FROM sys.databases
WHERE name = 'tempdb'
To make it more intuitive, you can run the script below, which will tell you how many days and hours Sql Server has been running. Minutes and seconds information will be truncated. If you need that, modify the script to get it yourself.
SELECT 'Sql Server Service has been running for about '
+ CAST((DATEDIFF(hh, create_date, GETDATE()))/24 AS varchar(3)) + ' days and '
+ CAST((DATEDIFF(hh, create_date, GETDATE())) % 24 AS varchar(2)) + ' hours'
FROM sys.databases
WHERE name = 'tempdb'
Source: How long SQL Server has been running
SELECT crdate FROM sysdatabases WHERE [name] = 'tempdb'
The above will work on SQL Server 2000, 2005 and 2008.
The logic is that the result from the above SQL returns the created date of the tempdb database, which SQL Server recreates every time it is restarted. Hence, the created date of tempdb is the startup time of the server.
I know this is super old, but Microsoft has added a new DMV with this information since this question was asked.
SELECT dosi.sqlserver_start_time
FROM sys.dm_os_sys_info AS dosi
Grabbed here
USE Master
GO
SET NOCOUNT ON
DECLARE #crdate DATETIME, #hr VARCHAR(50), #min VARCHAR(5)
SELECT #crdate=crdate FROM sysdatabases WHERE NAME='tempdb'
SELECT #hr=(DATEDIFF ( mi, #crdate,GETDATE()))/60
IF ((DATEDIFF ( mi, #crdate,GETDATE()))/60)=0
SELECT #min=(DATEDIFF ( mi, #crdate,GETDATE()))
ELSE
SELECT #min=(DATEDIFF ( mi, #crdate,GETDATE()))-((DATEDIFF( mi, #crdate,GETDATE()))/60)*60
PRINT 'SQL Server "' + CONVERT(VARCHAR(20),SERVERPROPERTY('SERVERNAME'))+'" is Online for the past '+#hr+' hours & '+#min+' minutes'
IF NOT EXISTS (SELECT 1 FROM master.dbo.sysprocesses WHERE program_name = N'SQLAgent - Generic Refresher')
BEGIN
PRINT 'SQL Server is running but SQL Server Agent <<NOT>> running'
END
ELSE BEGIN
PRINT 'SQL Server and SQL Server Agent both are running'
END
This simple query works for versions before SQL Server 2005 as well as recent ones:
SELECT
crdate AS startup,
DATEDIFF(s, crdate, GETDATE()) / 3600. / 24 AS uptime_days
FROM master..sysdatabases
WHERE name = 'tempdb'
I wrote a trigger that updates local table and similar table on linked server.
CREATE TRIGGER myTtableUpdate ON myTable
AFTER UPDATE
AS
IF (COLUMNS_UPDATED() > 0)
BEGIN
DECLARE #retval int;
BEGIN TRY
EXEC #retval = sys.sp_testlinkedserver N'my_linked_server';
END TRY
BEGIN CATCH
SET #retval = sign(##error);
END CATCH;
IF (#retval = 0)
BEGIN
UPDATE remoteTable SET remoteTable.datafield = i.datafield
FROM my_linked_server.remote_database.dbo.myTable remoteTable
INNER JOIN inserted i ON (remoteTable.id = i.id)
END
END -- end of trigger
Unfortunately when connection is down I get error message
'Msg 3616, Level 16, State 1, Line 2'
'Transaction doomed in trigger. Batch has been aborted'
and locally made update is rolled back.
Is there a way to maintain this error and keep local updates?
Note that I'm using SQL Server 2005 Express Edition on both PCs running Windows XP Pro.
edit1: SQL server is Express Edition
edit2: Both PCs run Windows XP Pro so these aren't servers
don't write to the remote server in the trigger.
create a local table to store rows that need to be pushed to the remote server
insert into this new local table in the trigger
create a job that runs every N minutes to insert from this local table into remote server.
this job can run a procedure that can test for the connection, and when it is back up, it will handle all rows in the new local table. It can process the rows in the local table this way:
declare #OutputTable table (RowID int not null)
insert into my_linked_server.remote_database.dbo.myTable remoteTable(...columns...)
OUTPUT INSERTED.RowID
INTO #OutputTable
SELECT ...columns...
from NewLocalTable
delete NewLocalTable
from NewLocalTable n
inner join #OutputTable o ON n.RowID=o.RowID
EDIT based OP comment
after inserting into this new local table start the job from the trigger (sp_start_job), it will run in its own scope. If you can't use sql server jobs, use xp_cmdshell to execute the stored procedure (lookup SQLCMD or ISQL or OSQL, I'm not sure what you have). still schedule the job every N minutes, so it will eventually run when the connection comes up.
Is at least one of the servers Workgroup edition or higher? You can use Service Broker to ship your records instead of linked servers, but it will not work between to Express editions due to licensing restrictions. Is a solution relying exclusively on SQL, offers reliability in case of incidents (one of the servers is unavailable) and your updates will propagate in real time (as soon as they are committed). My site has many examples on how to do this, you can start with this article here on how to achieve high message throughput.