I'm looking for a little guidance. I have an Access App that connects to a server to run SQL queries. I can test the connection (ping) prior to running any queries, but I am not able to gracefully handle when connection is lost mid-stream (which seems to happen too frequently).
I have err_Handing in-place, but I seem to get a nested collection of error messages, including:
3146 - ODBC Error
3151 - ODBC Connection Error
3704 - Object is Closed
2046 - Quit not available
>> Requires Ctl-Break, or Task Mgr to break loose...
I do account for long-duration queries with: db.QueryTimeout = 0; I don't think these are my my issue at this point.
To begin to address my issues, I recently converted over from Global Variables to TempVars, so my app no longer loses its mind with these handled and un-handled errors. Seems now I have marginally more control, but still my Access App gets hung in Err Msg hell.
My desired response to a LOST connection:
Trap the error condition
Message to the user announcing the situation
Write to log fie to capture current state
Graceful exit from Access
Any suggestions or pointers to begin to address this need?
Thank you!
You can freely use global variables (VBA) and they NEVER lose their values if you use a compiled accDE. So the conversion of such variables to tempVars really is not required. Since an accDE (compiled application) never loses VBA values (even without error handling), then the result is a far more robust and reliable application. And a compiled accDE also prevents the VBA code from becoming un-compiled, and also locks down the design of the application from being tampered with.
As for losing a connection, there is really not a viable solution at this point in time. At application start up you can check for a connection and gracefully exit by using this approach:
ACC2000: How to Trap ODBC Logon Error Messages
http://support.microsoft.com/kb/210319
However, during a session with bound forms and a loss of the network connection cannot really be trapped or dealt with in a graceful manor – the only real solution is to address the loss of connection and prevent it in the first place.
Related
I have an app that requires local users to Sync back to the SQL server periodically (event based, including upon Close/Exit).
My users have occasional internet/VPN issues that throw the expected "3146" error.
Problem:
When ODBC error is thrown, my app LOSES its mind (global variables are lost, etc.) and the app becomes utterly unusable. There are many subsequent layers of error messages thrown to my users, occasionally requiring a Ctl-Break to interrupt (or task manager).
Question:
I have an err_handler in every module that provides a structured error message. I am able to trap err_number "3146" in the err_handler module, where I attempt an abrupt "Application.Quit" (to avoid the subsequent err messages). I still get a couple subsequent err messages before the application fully terminates.
Is there a better approach to more gracefully handling "3146" errors?
Looking for some good ideas.
Thanks!
If you are handling the error then there should not be a problem. How you should be handling the error is to not do Application.Quit, you should actually do something about the error. A failed connection is not a reason to blow up your app.
Instead, think about caching data locally so that when the connection can be made you can perform your sync again. When you discover your connection failed, stop trying to connect, abort the syncing process, and tell your users "Hey, we couldn't sync now. You might be having VPN issues. Fix those and try to sync again." And all the while your data are still stored in your accdb so that if they go into work the next day and are hardwired into the network they can then sync successfully.
When using SQL pass-thru queries in MS Access, there is a default time-out of 60 seconds, at which point an instruction is sent to the remote server to cancel the request. Is there anyway to send this command from the keyboard similar to Access' own "Ctrl + Break" operation?
Firstly, understanding how Control-C cancels execution. They probably trap that key sequence, and do something special. I strongly suspect that oracle's client apps (SQL*Plus et al) are calling OCIBreak() behind the scenes, and passing in the handle to the server that they obtained when they executed the query with a previous OCI call.
I also suspect that Access isn't doing anything actively after 60 seconds; that's just the timeout it requests at time of execution query. Even more so, I'm beginning to wonder if Access is even requesting that timeout; everything I've read says that the ODBC driver does not support a query timeout, which makes me think it's just a client-side timeout, but I digress...
So - back to this OCIBreak() call. Here's the bad news: I don't think ODBC implements these calls. To be 100% sure, you'd have to take a look at the ODBC driver for oracle sources, but everything I've read indicates that the API call is not exposed.
For reference, I've been googling with these search terms in combination with "OBDC":
ORA-01013 (error when a user cancelled an operation, or when an operation times out)
OCIBreak (OCI function which cancels a pending operation)
--- EDIT #1 ---
As a side note, I really believe that Access is just giving up, and not sending any type of cancel command when the Pass-Through timeout is exceeded. If you take a look at this kb article, the ODBC Driver doesn't even support a query timeout:
PRB: Connection Timeout and Query Timeout Not Supported with Microsoft Oracle ODBC Driver and OLE DB Provider
After the elapsed time, Access probably just stops listening for results. If you were to ask oracle for a list of queries that are still executing, I strongly suspect you'd still see yours listed.
--- EDIT #2 ---
As far as implementing your own "cancel" -- which isn't really a cancel, more of a "keep the UI responsive regardless of the state of a query" -- the keyword here is going be asynchronous. You're going to want to rewrite your code to execute asynchronously so that it isn't blocking the message pump for your UI. I'd start googling for "async query access" and see what pops up. One SO result came up:
Running asynchronous query in MS Access
as well as a decent starting point at xtremevbtalk.com:
http://www.xtremevbtalk.com/showthread.php?t=82631
In effect, instead of firing off code that blocks execution until either a timeout occurs or a result set is returned, you'll be asking access to kick off the code behind the scenes. You'll then set up an event that fires when something further happens, such as letting the user know that the timeout occurred (timeout failure), populating a grid with results (success), etc...)
I have an application which connects to a MySql database using Delphi's TAdoConnection object. This is a very query intensive application. So I create the connection and keep it open to avoid the high resource expense of open/closing database connections. But obviously problems can arise (database restart, network connection failure, etc). So I have built in code to free my database object, recreate it, and reconnect when queries fail.
I have a common function to connect to the database. The relevant code is this:
try
AdoConnection.open;
result := Adoconnection.Connected
except
result := False;
......
end;
I ran some test by turning on and off the MySql database. Everything works fine if the database is off on application startup (i.e. it properly throws an exception). However, if I turn off the database after the application has already successfully connected, subsequent re-connections do not throw exceptions, and additionally falsley report true for AdoConnection.Connected. I am sure the connection object had been freed/recreated first.
It seems there is some sort of caching mechanism going on here (most likely at the hardware/driver level - not application level). Anyone have any ideas?
I observed this also.
Ideas for dealing with it:
If you get an error on running a query then check if it's a connection issue and if so try to reconnect and then run the query again.
If your program uses a timer and waits a while between running batches of queries then perform a simple query (maybe "select now()") before each batch and if this fails then try to reconnect.
I wrote a program running as a service that need to frequently gain access to MS Access database. After a period of time, my program exits automatically, then I open my MS Access database with Office, it says it is broken!
It seems very strange as my program do just some very common database access: insert, select and delete. Why is it always broken after running a period of time?
Has anyone here ever run into such problem? Any advice is appreciated.
Almost all problems of this nature when dealing with Access (or Excel, Outlook...) are due to not correctly releasing (i.e. cleaning up) resources.
Suggest you post any errors you are seeing.
Access does not recover gracefully if a program terminates without closing the database. There is a dirty flag that Access uses, and the repair feature will reset it (amongst other things), but typically, I don't recommend Access where any robust handling is required.
Under high traffic my mysql 5.0.45 server /Apache2/ CentOS 5 is getting "Error establishing mySQL database connection". I need to find the root cause.
I would very much appreciate any pointer to information about the procedure I should take to find the cause (memory limit, thread limits, CPU load, slow queries etc, large dataset, wrong keys ...) I would assume it involves looking at relevant log files etc....
Thank you.
That particular error message sounds like it's being generated by your application, and not by a system library. MySQL has functionality to report the specific errors that are occurring, so your best bet would be to utilize that in some way.
For instance, if you were using PHP, there is a function called mysql_error() that returns specifics about the last error encountered (too many connections, etc). You would put in some error handling near your connection call, and log the mysql_error() results if it failed.
You didn't mention what language you were using, but the MySQL libraries would provide the same functionality to whichever you are using. I'd suggest modifying your application code to take advantage of it.
I'm willing to bet this is because you're hitting the max user limit allowed by the mysql server but in general, do print the mysql errors, if not to the screen but at least to the log, or email.