sp_send_dbmail blocks and causes PREEMPTIVE_OS_GETPROCADDRESS - sql

I have a strange issue with msdb.dbo.sp_send_dbmailwithin a stored procedure (code simplified):
SET NOCOUNT ON;
SET XACT_ABORT ON;
-- ...
SET #msg = N'...';
SET #filename = N'...';
EXEC msdb.dbo.sp_send_dbmail
#recipients = 'mailaddr#example.com'
, #blind_copy_recipients = 'another_mailaddr#example.com'
, #from_address = 'senders_mail#example.com'
, #subject = N'...'
, #body = #msg
, #query = N'SET NOCOUNT ON; SELECT <something> FROM <a_view>;'
, #execute_query_database = N'<same database the proc resides in>'
, #query_result_width = 8000
, #attach_query_result_as_file = 1
, #query_attachment_filename = #filename
, #query_result_header = 1
, #query_result_separator = ';'
, #query_result_no_padding = 1
, #exclude_query_output = 1;
I have a database user which is member of db_datareaderand EXECUTEpermissions for the stored procedure. Furthermore the assigned server login is mapped to msdband a member of the DatabaseMailUserRole. There is only 1 single mail profile which is public and flagged as default.
Everything works fine from SSMS: connect with the user's credentials and execute the stored procedure. Great!
The first oddity: if I'm logged in as sysadmin and try to EXECUTE AS it doesn't work. Okay, I found something that points out that there are issues with this.
But the main issue is this: I call the procedure from a 3rd party Java application which connects using the jTDS driver (don't know if this is important). The applicaton executes the procedure ... and nothing else happened (no log entries, the task freezes).
In the activity monitor I see the following:
Process <...>
Database master (??? I've never connected to this
db!)
Task State Running
Wait Type PREEMPTIVE_OS_GETPROCADDRESS
Head Blocker 1
To make things worse I cannot kill this process. If I try this the Command column in the activity monitor shows only KILLED/ROLLBACK.
KILL <PROCESS-ID>shows
spid <...>: Transaction rollback in progress. Estimated rollback completion: 0% Estimated time left: 0 seconds.
I have to restart the whole instance to get rid of the process.
What is happening here?

Finally I found the answer here: blocking from xp_sysmail_format_query waittype of preemptive_os_getprocaddress
It seems that the Java application opens a transaction explicitly (there are 2 calls to stored procedures consecutively). After setting the Auto-Commit option of the database adapter to on everything work's fine.

Related

Tracking process of unknown origin, on SQL Server

I need some out-of-the-box thinking on this issue. It's weird.
I have a SQL Server environment (production) where I get a sporadic error executing a procedure.
dbo.proc_1_$sp
...
begin try
BEGIN
SELECT #errmsg = 'failed to execute proc2_$sp'
EXEC proc2_$sp;
END;
...
catch
... etc
EXEC proc2_$sp fails.
It returns error
failed to execute proc2_$sp
to a process log table.
The problem is... I don't execute dbo.proc_1_$sp.
I want to find out what executes it. It could be a test environment pointing to production, it could be a test script someone left running.
I want to know the hostname, the login name, or whatever info I can catch on this process.
I can't leave SQL Server Profiler trace on. I tried, but it's a prod environment and I can't let the trace running for hours.
The only way I can think of is to update the error message with more info, as below.
The problem is, since I don't know the login name, I can't ensure the user will have access to sys.sysprocesses and I might get a crash instead.
Any other suggestions on how I can grab process information without worrying about permission issues?
dbo.proc_1_$sp
...
begin try
BEGIN
SELECT #errmsg = 'failed to execute proc2_$sp'
select #errmsg = #errmsg + ' login_time:'+convert(nvarchar, login_time, 9)+' hostname:'+ltrim(rtrim(hostname)) + ' program_name:'+ltrim(rtrim(program_name))+' loginame:'+loginame
FROM sys.sysprocesses WHERE spid = ##SPID
EXEC proc2_$sp;
END;
...
catch
... etc

SQL server mail function sp_send_cdontsmail

i wrote a procedure in which i tried to send mail using below command.
EXEC Sp_send_cdontsmail 'from','to','Test','TEST DATA'
After executing its showing "Command(s) completed successfully."
but i am not getting any mail.please help me on this.
You need to configure Database Mail and then use sp_send_dbmail to send mail. This is a supported procedure, part of the SQL Server.
PS. I am aware that out there some code sample circulates that advocates something along the lines of:
CREATE PROCEDURE [dbo].[sp_send_cdontsmail]
...
EXEC #hr = master..sp_OACreate 'CDONTS.NewMail', #MailID OUT
EXEC #hr = master..sp_OASetProperty #MailID, 'From',#From
EXEC #hr = master..sp_OASetProperty #MailID, 'Body', #Body
...
This is horrible code. As one can easily see there is absolutely 0 (zero, nada, zip) error checking in this code. Any failure will be reported as 'success'. COM interop will not raise T-SQL notification messages, is all in the HRESULT, which goes unchecked. Steer away from such code.

Azure database copy, wait for ready state

I am making new Azure databases now and then and without any human interaction, by using a template database and azure copy database t-sql script.
After reading a few caveats I wonder what is the best way to wait for the copied database to be ready.
I have posted my own answer but it could end up in an infinite loop if the database copy fails.
What is the best way to be sure that the copying is done. This is very important as you are only allowed one copy database command at a time. I'm using an Azure worker with a c# queue that creates the databases as nessesary.
This is how I'm doing it now. This should work but unfortunatly errors when copying are rare.
declare
#sName varchar(max),
#sState varchar(max),
#iState int,
#sDbName varchar(50)
set #sDbName = 'myDbName'
set #iState = 7 --copying
while #iState = 7
begin
WAITFOR DELAY '00:00:05'
SELECT #sName = name, #iState = state, #sState = state_desc FROM sys.databases WHERE name = #sDbName
end
SELECT name, state,state_desc FROM sys.databases WHERE name = #sDbName
This code is actually run from a Azure worker in c#
Edit:
If you want more granular approch use sys.dm_database_copies
But otherwise remember that this sql returns the state as integer, and its only successfull if the state ==0 Othervise the copy has failed.
the states are:
0 = ONLINE
1 = RESTORING
2 = RECOVERING
3 = RECOVERY_PENDING
4 = SUSPECT
5 = EMERGENCY
6 = OFFLINE
7 = COPYING (Applies to Windows Azure SQL Database)
Windows Azure SQL Database returns the states 0, 1, 4, and 7.

SQL Server OLEDB error with no details

I have a SQL Server Agent job running, which uses a stored procedure to do several operations, then exports some data to an xls spreadsheet and emails that spreadsheet. Most of the time it works, but several times a month the job fails with the error:
OLE DB provider 'Microsoft.Jet.OLEDB.4.0' reported an error. The provider did not give any information about the error. [SQLSTATE 42000] (Error 7399). The step failed.
Thanks, Microsoft, for the detailed error message. Anyway, the short term fix is usually to simply re-run the job. Usually this works, but in rarer cases it does not, and I must restart the SQL Server instance.
Here is how my code interacts with OLEDB:
Insert into OPENROWSET('Microsoft.Jet.OLEDB.4.0', 'Excel 5.0;Database=\\Excel\POStatus\POStatus.xls;',
'SELECT * FROM [POStatus$]')
Select --Tons of columns with tons of math and functions
FROM --5 tables joined together (left joins)
WHERE -- Tons of where conditions
Order by --Case statement for custom sorting
Set #vCommand = 'copy \\Excel\POStatus\POStatus.xls \\Excel\POStatus\POStatus_' + #vDate + '.xls'
EXEC master..xp_cmdshell #vCommand , NO_OUTPUT
... omitted for brevity...
Set #nvSubject = ' POStatus ' + #vDate
Set #nvMessage = ' This is an automated message, please respond to the IS department, thank you '
Set #nvMessage = #nvMessage + char(13) + char(10)
Set #nvAttachments = '\\Excel\POStatus\POStatus_' + #vDate + '.xls'
Exec master..xp_sendmail
#recipients = #nvRecipients , #copy_recipients = #nvCopy_recipients ,
#subject = #nvSubject , #message = #nvMessage ,
#query = #nvQuery , #width = #iWidth , #attachments = #nvAttachments
So, what is the cause of this, and how can I prevent it?
When you call OPENROWSET, it load the DLL for OLEDB provider for Excel. These operations happens inside the SQL Server Stack memory. When a lot of call to older DLL (ActiveX/COM) are made, it's not impossible that your stack might get full. You can resolve this in 2 ways:
1) You make these operations outside a TSQL code. You can use a SSIS package for example but you have to change your code not to use OPENROWSET. You can use the DTS Wizard to do most of the job. This is my personnal recommandation !
2) You can also set SQL Server to have a bigger memory Stack by using the -g command parameter. I think 256 MB is the default and you can set it to 512. To do that you need to open the SQL Server Configuration Manager. Depending on your version, you should have a place to change the "Startup Parameters"

SQL Server 2005 Asnyc stored procedure

I am currently having problems calling a stored procedure async from within a insert-update-trigger. For this I m using the service broker.
--message type
CREATE MESSAGE TYPE [TheMessage] VALIDATION = NONE
--contract
CREATE CONTRACT [TheContract] ([TheMessage] SENT BY ANY);
--queue
CREATE QUEUE [TheQueue] WITH ACTIVATION
(STATUS = ON, MAX_QUEUE_READERS = 1,
PROCEDURE_NAME = TheStoreProcedure,
EXECUTE AS OWNER);
--service
CREATE SERVICE [TheService] ON QUEUE [TheQueue] ([TheContract]);
Within the trigger:
DECLARE #Handle UNIQUEIDENTIFIER;
BEGIN DIALOG CONVERSATION #Handle
FROM SERVICE [TheService]
TO SERVICE 'TheService'
ON CONTRACT [TheContract]
WITH ENCRYPTION = OFF;
SEND ON CONVERSATION #Handle
MESSAGE TYPE [TheMessage](N'some data');
Within the stored procedure:
DECLARE #Handle UNIQUEIDENTIFIER;
DECLARE #MessageType SYSNAME;
RECEIVE TOP (1)
#Handle = conversation_handle,
#MessageType = message_type_name
FROM [TheQueue];
IF(#Handle IS NOT NULL)
BEGIN
-- some statements
END
This setup doesn't seem to work. The trigger does not throw any errors so I assume the message is queued. But the receive within the stored doesn't seem to work. None of my statements are being executed.
Check if the message isn't retained in sys.transmission_queue. Transmission_status column should explain why the message isn't delivered.
Check if the message is in the queue: SELECT ... FROM [TheQueue]. If the message is there and the procedure didn't activate check the queue's is_receive_enabled status in sys.service_queues. If the queue is disabled, you probably rolled back 5 receives in a row during testing and triggered the poison message mechanism.
If the queue is enabled, check the queue monitors status, see Understanding Queue Monitors.
If the message is neither in the queue nor in transmission queue, it must been consumed by the activated procedure. Verify your ERRORLOG for any error output. Disable activation, send a message again, then run the procedure manually from an SSMS query window see if you get any error message.
Mae sure your activated procedure does not fall into the traps of the EXECUTE AS context. See Why does feature … not work under activation? and Call a procedure in another database from an activated procedure
Ok, thanks for your answers, I fixed it.
The problem was that the service broker was disabled..
USE AdventureWorks
GO
ALTER DATABASE AdventureWorks SET SINGLE_USER WITH ROLLBACK IMMEDIATE
ALTER DATABASE AdventureWorks SET ENABLE_BROKER
ALTER DATABASE AdventureWorks SET MULTI_USER
GO