Groups | Blog | Home
all groups > sql server clients > april 2004 >

sql server clients : A TOUGH ONE - audit Login, Audit Logout connection


phil.smith NO[at]SPAM informatics.co.uk
4/28/2004 5:25:45 AM
Hi all:


Hope you can shed some light on this. we have a Vb6 app connecting to
a slq server database using ado 2.6. when each client is started they
initialize a connection object which is kept open for the life cycle
of the client (i know this not recommended but it is an inherited
problem).

Our site was reporting errors which were attributed to loss of client
connection to the server. As we still haven't found a clear way of
alerting the client when it has loosed its connection to the server
((1)if anyone has a suggestion let me know)- the Recordset.state
property and Recordset events are useless for this.

Our solution for this was - when ever we pass the connection object
to a recorded, internal to the connection object we test the
connection to the server by executing a "Select @@Version" on the
server using a prepared command object. if this test fails then we try
re-establish the connection , which is looped on the
connection.timeout. so the user has the choice to reconnect or exit
the app.

now running a trace using profiler with audit
login/logout,ClentProcessID, spid and the other main event, when the
app starts up it gets its unique ClentProcessID & spid from sql, so we
can identify the app and its connection (audit login) at intensive
parts of the code for some unknown reason an additional spid connects
for the same ClentProcessID and this can carry on for up to 5 layers
so what the trace looks like is....

ClientProccessID|SPID|EventClass|
---------------------------------
444 | 51 |SQL:Batchcomplete
444 | 51 |SQL:Batchcomplete
444 | 51 |SQL:Batchcomplete
444 | 52 |Audit Login
444 | 52 |SQL:Batchcomplete
444 | 52 |Audit Out
444 | 52 |Audit Login
444 | 52 |SQL:Batchcomplete
444 | 53 |Audit Login
444 | 53 |SQL:Batchcomplete
444 | 53 |Audit Out
444 | 52 |Audit Out
444 | 51 |SQL:Batchcomplete
444 | 51 |SQL:Batchcomplete
444 | 51 |SQL:Batchcomplete

you can see these are nested and can be upto 5 levels deep. (2) we
think what is happening is that ADO is just creating additional
connections at times of have traffic without us knowing which may be
contributing to our loss off connection, is there any way to further
track this or clarify this.


we don't think it is a connection pooling problem as this has been
switch off, and we have taken into account spid's for other apps
connected to the server.

I hope you have enough info. so if anyone has a solution to (1) or can
confirm (2) it would be much appreciated.


Ilya Margolin
4/28/2004 9:26:46 AM
Phil,

First off you can use <ADODBConnection object>.Status = adStatusOpen.
<ADODBRecordSet object>.Status will give status of a recordset, not of a
connection. Second, we've never experienced ADO dropping connection by
itself for no good reason. A connection will be dropped in only two cases:
you explicitly terminate connection or connection object goes out of your
code scope. So, dig through the code again...

Ilya

[quoted text, click to view]

Zach Wells
4/28/2004 11:22:33 AM
[quoted text, click to view]

If you took the time to create the workaround of "select @@version", why
don't you just change the code to create a connection object as
necessary instead of relying on the global one?

rboyd NO[at]SPAM onlinemicrosoft.com
4/28/2004 7:37:28 PM
It is not uncommon for the underlying connection methods (OLDEB, DAO etc)
to create additional connections when it feels it is necessary. I doubt
that this is a contributing factor to your connectiosn being dropped.

Have you looked at possible timeout problems running queries? This can
cause a connection to be dropped.

Rand
This posting is provided "as is" with no warranties and confers no rights.
Craig Kelly
4/28/2004 9:41:08 PM
[quoted text, click to view]

<snip>

[quoted text, click to view]

<snip>

[quoted text, click to view]

<snip>

Phil,

As has already been pointed out, "hidden" connections can be created behind
your back. The most common situation I know of with ADO is opening multiple
recordsets on a connection object: if there's an open recordset on a
connection, opening a second recordset creates a hidden connection behind
the scenes.

As for strange connection failures: we've observed one situation with ADO
like this... if the physical Ethernet link is broken and then some kind of
network operation on the Connection object is requested, an error will be
thrown, the Connection's State property will still be adStateOpen, and any
attempt to use the Connection object will fail. Even after the physical
link is re-established, the connection object will no longer work (even
though the State property shows it as open).

We found this out because one of our main Ethernet switches was not on a UPS
and on a outlet not connected to the backup generator and main UPS (I know,
I know, don't get me started). In any event, when that switch lost and
regained power, anyone connected to the switch with an ADO connection was
broken (assuming they'd been doing anything). We were able to reproduce
this for testing purposes by opening a connection, removing the Ethernet
cable on a computer, issuing a simple select on the Connection object, and
then re-connecting the Ethernet cable.

Our applications use a wrapper class around the ADO connection, so our
solution was to detect this particular state when a database operation
raised an error. If we found the state had occurred, we would save the
connection string, close the connection, destroy it, create a new
connection, and open the new connection with the same connection string. I'm
leaving out retry logic and our application-level transaction tracking, but
you get the idea...

Here's the VB 6 code we used for detecting this (editing in my news editor,
so not guaranteed to be syntax error free):

Private Function LinkFail(ByVal conn As Connection) As Boolean
Dim e As ADODB.Error
Dim bLinkFail As Boolean

If conn Is Nothing Then
bLinkFail = False
ElseIf conn.State <> adStateOpen Then
bLinkFail = False
Else
For Each e In conn.Errors
'Not the cleanest thing in the world, but it works
If Trim$(UCase$(e.SQLState)) = "08S01" Then
bLinkFail = True
Exit For
End If
Next e
End If

LinkFail = bLinkFail
End Function

Craig

AddThis Social Bookmark Button