MS Office 365 ProPlus, Access 2007 - 2016
Here's the problem...
I have a MS Access DB on a shared file server which many users from many sites can access to make a few small edits on a weekly basis. Occasionally a user with an active connection will abruptly shut down their client server (their laptop) leaving a dangling connection to the DB which results in a DB in limbo which cannot be opened. Messages indicate that it's corrupted and the option to repair it just hangs. Not a big deal because I have a task scheduler job that backs-up (copies) the DB every 3 hours and I can just use the most recent backup to restore. But I can't even delete/clobber the DB with the backup because the dangling process is connected and Windows refuses to let me delete it (which is a problem in and of itself IMO).
The solution is to find the connection, kill it, delete the .accdb and the .laccdb, then replace it with the backup. But unfortunately, I don't have privs to find/kill the connection, so I have to engage someone in IT to go do that (can take a long time & the person I get often doesn't know how to do this).
What would really alleviate the problem is an automated DB disconnect for client processes that are idle for more than x minutes. I saw something similar to this using a form. But my users edit the cells in the tables directly (they like the ExCel style editing over forms). I searched DB options and don't see an option to set up a idle timeout/disconnect for the DB in general.
Question: Is there a way to set up an idle timeout like this which will close the DB connection after x minutes?
Question: Given the problem stated, is there another way to prevent these DB "corruptions". Everything I've read about this is along the lines of "educate your users to close Access when done". There are too many users and I doubt they'll pay attention.
Question: Access seems like a not-so robust DB for this, but the users really want the ExCel style interface (edit cells in records without forms). The record level locking mech seems to work well. And I love the fact that I can easily set up triggers and constraints to maintain data quality, query the thing with SQL, etc... (ExCel not so good for this). But if there's a better alternative than Access, I'm all ears.
Thanks for any ideas !
This is a pretty common problem, with no easy solutions.
There are two main approaches for this problem:
Use a hidden form with a timer that opens on startup. Have the form check every now and then if a form/datasheet is open, and if the active record or active control on that form/datasheet changes. If it doesn't for a period of time, close down Access.
The code required for this method is described here on MS docs, it only requires a few additions for datasheets (tables/queries).
This method has the limitation that you're shutting down Access for users that are multitasking. If they don't touch Access a while, it's gone, and that's not great UX.
Another limitation here is that there's a chance a user is kicked out unnecessarily, for example because he's moving data from another application and thus always has his cursor on a new record while actively using the database.
Start a timer on startup using WinAPI (could also be a hidden form with a timer instead). Use GetLastInputInfo to verify that the user hasn't sent any input for a set period on the timer. If it hasn't, then close down Access.
This has the limitation that any input (e.g. a mouse that moves a tiny bit when walking past an unsteady desk) will reset the timer.
If you have trouble implementing either of these, I can provide sample code.
Your better option - because of the limitations explained by Erik - would be (if not done already) to split the database into a frontend and a backend, convert the backend to SQL Server (Express edition is free to use), and distribute then frontend to the user's machines using a method as described in my article (if you don't have an account, browse to the link "Read the full article"):
Deploy and update a Microsoft Access application with one click
That would completely free you from the daunting tasks that keep you busy.
Here's something that shows prmoise, from
https://bytes.com/topic/access/answers/942650-can-you-force-access-quit-when-pc-goes-into-standby-mode
Idea is to run a vbs that runs access. If a power down event is sensed, it will disconnect the DB instead of leaving a dangling process.
Option Explicit
Dim objAccess, objWMIService, colItems
Set objAccess = CreateObject("Access.Application")
objAccess.Visible = True
objAccess.OpenCurrentDatabase "\\vausamd20\SCBUDV_Infra\dbg_taskdb.accdb"
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set colItems = objWMIService.ExecNotificationQuery("Select * from
Win32_PowerManagementEvent")
Do While True
If colItems.NextEvent.EventType = 4 Then
objAccess.Quit
Set objAccess = Nothing
Set colItems = Nothing
Set objWMIService = Nothing
Exit Do
End If
Loop
Open to comments if anyone thinks this is a good or bad idea !
Related
I have a connection speed problem when someone running a query from a Access database. The delay for loading data significantly increase when a user runs new queries after some minutes of not using the app.
I found this article for fixing this issue, I did all the steps but the codes were not working for me! I have one single database and the app working on multi-user environment (9 people).
Does anyone have any solutions/suggestions?
Thanks,
Peyman
Keep in mind that a persistent connection does not always fix slow network issues. However in a rather high % of cases it does.
The most easy way to “test” if a persistent connection will fix your issue(s) is to simply open up a linked table in your front end. (Any table will do as long as it is a linked table pointing to your back end). NOW run your code or query. If it runs fast then a persistent connection will help your case. If the above simple 3 second test does NOT fix performance, then a persistent connection while recommend and is a good idea – it will not fix your performance issue.
So try the above. If the above fixes your issues, then you can pursue one of several means to achieve a persistent connection.
Some simple ways to force or always have a connection open to the back end:
Simply open some form bound to a linked table. It could even be a “test” form. Right after you open the form, you can set its visible property = false.
Another way is to define a global record set variable and open that record set on start up to a table in the back end. Eg:
Set rst = currentdb.OpenRecordSet("select * from tblTest")
Keep in mind that if you using a non-compiled application (accDB as opposed to a compiled accDE) than any un-handled error will blow out such global variables and thus your persistent connection will be lost.
So before you go on a wild goose chase you can test with a persistent connection by simply opening a linked table in your front end, minimise it and then run your test code or whatever it is that is slow. If you don’t see a speed up, then the performance issue(s) you have will not be solved by using a persistent connection.
I have an MS access system on a network with 15 users. The Front end is installed on users C:\ and BE on a mapped drive X:.The front end is about 8 meg, backend around 25.
Since day 1, one user constantly (every 30 mins at best) and some other users have a network interrupted error. Apart from being quite annoying to the users, this causes a temporarily masked/hidden issue where update queries run without error on 2 tables but do not update actually update/insert data.
A compact and repair resolves the issue, but is not feasible to run daily as users have the system open throughout the day. This is such a headache that I've had to write code to check that the data has been written after each query is run to detect if the issue is present.
Both myself and IT are 3rd parties to the business and are in the difficult opposing positions of "its your the network" and "its your database". Thankfully its all calm and peaceful but its not getting a solution for the client.
I've installed MS access FE/BE systems on over a hundred networks over the last 10 years and only ever seen the same issue on a peer to peer network. I'm aware that Access is very picky about network stability, but am faced with users who don't believe that there is a problem with the network as their email works and the internet radio doesn't drop out.
What I'm hoping to get assistance with here is either a tool / method that can test a network for stability / robustness with MS access and prove either one of us right/wrong with MS access or perhaps some advice on how I could move forward on this deadlock.
Thanks
I have seen a similar instance with damaged cables. A client of mine had mice that chewed through part of the cable, causing an intermittent interruption. Also, in another case, a cubicle wall was on top of the network cable (poor cable installation) and causing a short.
In order to bypass Access's need for constant network connection, I have my systems create local temporary tables for any view, and a local, 1-record table for any detail form that they are actively editing. Once they hit 'save' it runs the update query, and once done, no active connection with the server is needed again. It allows me to run much faster access systems, and eliminated the need for stable wireless or Ethernet. It does require quite a bit of structure change at first - as you will have to insert code to create local temporary tables in the FE file, and also code in an UPDATE Sequence in the AFTERUPDATE Form events too - but the time that it is has saved me and my users has been tremendous.
To put in in perspective, i have 1200+ users in the same Access database in a given week (sometimes 400+ in a day) and since they only 'pull' data from the server to make local table copies, there are only a handful of connections at any one time. My users can now dock and undock from their desks without needing to close the database.
We have multi user frontend/backend MS Access 2010 application. We added a process that will close remote frontends when we want to do work on backend such as compact and repair. This is timer based check on table field that if has certain value will close the application.
I do two checks to see if users are connected to database:
i have login/logout process and can see who is still logged in (its form based so is fallible eg they close form but frontend is still open).
i used .ldb file viewer to see if anything is still connected
Two questions:
is there any possibility that a connection to backed could exist if it wasn't viewable with ldb viewer?
is there any bullet proof 100% certain way to forcefully disconnect all connections from backend?
Users put "locks" into an LDB. An LDB is a kind of database of locks for MS Access.
Users also put "locks" onto LDB's and MDB's. These locks are part of the native database primitives provided by Windows and Windows networking.
If there are no locks IN the ldb, the user is not writing into the MDB.
If there are no locks ON the mdb, the user is not using that Windows/Networking service.
To get exclusive locking on an MDB, you need both. MSAccess won't let you exclusive lock while the LDB has entries showing someone else is using the database, and Windows won't give you an exclusive lock while it has locks showing someone else is using the database.
To 100% bulletproof empty the LDB, you delete the LDB. That is why Access always attempts to delete the LDB on close. If Access crashes, or the network is disconnected, or the PC or Server is turned off, the LDB will have data ("locks") that have not been deleted. You get rid of them by deleting the LDB.
Access won't be able to delete the LDB if a user still has Windows/Network locks on the LDB. Since Access is ignoring existing "lock" entries to clear broken "lock" entries, this is how Access/Windows prevents Access deleting the LDB while another user is still using it.
If EITHER the Windows locks or the Access/LDB "locks" exist, you can't get exclusive ownership. If ONLY the Access/LDB "locks" exist, you can delete the LDB, and then get exclusive ownership.
If ANY Windows/Network locks exist, nothing you do with Access can allow you to disconnect another person from the network. You need to go to the Server/PC that hosts the file, and force the disconnection. Access is not a network administration program that does this for you.
Last I looked, Windows Server was set by default to time-out broken file connections 15 minutes after the network session was lost. So if you turn off a PC, wait 15 minutes, then the Windows/Network locks will go (default timing). Alternatively: Admin tools, Computer Management,System Tools,Shared Folders, Sessions. Select the file you wish to unlock, and delete the session.
A fix exists, and I have it in place for an MS-Access Application I maintain. However, it's not convenient, and it's not simple to implement.
First, some background on locking files and the locked file.
The locking file is a useful tool but it's an indicator, not the actual lock: you can edit it but that has no effect.
Live MS-Access sessions can keep a file lock on the .accdb or .mdb back-end database file if they edit data, change an object (eg: index a table) or perform a maintenance task. The last two items in that list are rare - it takes some effort to affect another database file outside the one you've opened in your session, but it is sometimes observed in the wild - but closing those sessions should release the lock and almost always will.
Crashed MS-Access sessions can keep a file lock on the .accdb or .mdb back-end database file. Forced restarts of the offending machines should release the lock, and mostly will.
You can trace those using the lock file (.ldb or .laccdb)
Third-party reporting applications using ODBC or ADO to your Access database should have their connections set read-only, so that they can't lock the file. If you're lucky, the system owners use a dsn file you control, and you can see that setting.
Some reporting apps, like QLikView, are opaque interfaces that demand the full filename and nobody knows what happens next: maybe it locks, maybe it doesn't. You have no way of knowing.
Some reporting apps - and Excel Pivot Tables - may link to your db, and the owners simply don't tell you. If their connections are badly configured, they can lock your table while retrieving: and terminating the client session can leave the lock in place. Bored Excel users watching a slow pivot 'refresh' do this all the time.
Worse, some third-party systems may well need to write data: this should be avoided - go through the Access client application! - but you don't always get to make that decision.
If you're lucky, the connection object is configured correctly, so the machine ID is in the connection string, ensuring it'll turn up in the locking file and allow you to locate the machine with the lock...
Maybe they do that: often they don't.
...Note that row-locking queries, page-locking queries, and table-locking queries are functionally identical for the issue that matters to you: if you need to do something (like compact and repair) at the 'file' level, the file is locked against you. Until that lock is released, you're locked out.
You may or may not be able to identify the machine. You may or may not be able to force them off the network. They may or not release the lock successfully in normal operation, and they almost certainly won't if they crash out.
So: it's not a pretty picture.
Your Best solution, in a corporate environment, is to have a direct line to a network administrator with the 'finger' tool to identify who is locking the database file, the ability to contact the user, and the ability to disconnect the offending session.
The modes of failure are:
If your organisational structures do not allow you to establish that
line of communication, you're screwed.
If your organisation's network administrators do not have the ability
or the authority to do that in a useful timeframe, you're screwed.
If your organisation's network administrator chooses not to do it,
you're screwed.
However, I do have a fix in place for my MS-Access Application:
The workaround I use is extremely aggressive - not quite the 'nuclear option' of putting a shovel through the building's power supply, or giving in to the sysadmin's demands for human sacrifice, but deeply unpleasant and a ridiculous amount of work to implement:
Configure the clients - your MS-Access front-end applications - to
switch between named back-end databases easily.
Likewise, the dsn files you have written and allowed other apps to
use should be accessible to a pre-existing script to edit the
'DBQ='or 'Data Source=' clause to a new filename.
Grab a copy of the database file, take it down to a local temp
folder for the maintenance work you needed to do, and post it back
up to your application's 'Data' folder under a new name.
Now run the 'Change back-end' script or VBA function...
...And to hell with anyone else who's using the old, locked,
back-end file.
Hint: implementing your front-end application so that it's regularly polling the back-end database (or some other resource, your worst case scenario is a total lockout) for a 'Maintenance shutdown' or 'Change database' instruction is a smart thing to put in your 'Main Menu' form's timer event.
Also, there's code out there to automate switching the source db for linked tables.
"I do two checks to see if users are connected to database"
If you need to open the db exclusively, you can skip the other checks and just check whether you can do it.
Public Function CheckExclusive(ByVal pFullPath As String) As Boolean
Dim blnReturn As Boolean
Dim cn As Object
Dim strConnection As String
On Error GoTo ErrorHandler
strConnection = "Provider=" & _
CurrentProject.Connection.Provider & _
";Data Source=" & pFullPath & ";"
Set cn = CreateObject("ADODB.Connection")
cn.Mode = 12& ' adModeShareExclusive '
cn.Open strConnection
blnReturn = True
cn.Close
ExitHere:
On Error Resume Next
Set cn = Nothing
On Error GoTo 0
CheckExclusive = blnReturn
Exit Function
ErrorHandler:
blnReturn = False
GoTo ExitHere
End Function
Then call that function with the full path to your db file.
If CheckExclusive("C:\SomeFolder\YourDb.mdb") = True Then
' do what you need here which requires exclusive access: '
' make backup; compact; whatever '
End If
is there any possibility that a connection to backed could exist if it
wasn't viewable with ldb viewer?
Yes, I have had on numerous occasions had issues where the the backend was locked but I could not see anything with an ldb viewer. In these cases, we have even resulted in doing hard-shutdown on the machines that users access the DB from. Awful solution but in times of need you are sometimes desperate.
is there any bullet proof 100% certain way to forcefully disconnect
all connections from backend?
No, I have not been able to find a 100% way to force everyone out of the backend DB. The closest thing that I found to perfect was using Chris Symonds Timeout-Force Out code located on Utter Access
This database accomplishes several tasks:
Allows developer to go to any PC using db and force all users off a split db so that the developer can open db exclusively to
modify/maintain db.
Kicks users off db if they haven’t used db in a specified number of minutes set by developer.
Allows developer to specify a time each day to force all users off split db and close the db for backup, compile or whatever.
All functions are optional and may be bypassed with no extra coding, use only what you need for each db.
I implemented his code and it works about 99% of the time, but there are still those occasions where MS Access gets a bit touchy and I cannot see why the DB is locked or force-everyone out.
I have an application that connects to a 3rd party. They fire web-hooks simultaneously at a time. Sometimes the hooks are about 1000 and over. The problem is that, my script connects to a database and save the hooks. These 1000 queries fired simultaneously on my system makes the system goes off. How effectively can i handle the web hooks?
thanks.
What you can do is, after every query, is close the connection. This will ensure that no connection stays open or is stacked on top of each other.
You will have to re-initiate the connection before launching a new query of course.
You could also increase the number of connection allowed to your MySQL database. This should be changed in your MySQL configuration (usually at /etc/mysql/my.conf ( http://dev.mysql.com/tech-resources/articles/mysql_intro.html )) by changing the "max_connections" variable/configuration value. ( http://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html#sysvar_max_connections )
Good luck and if you have any questions don't hesitate to ask.
Best regards,
We've inherited a rather large Access DB that has some very strange (and unsettling) behaviour: Some updates to the database are lost. What can we do to avoid this? Are there any settings in Access to provide better transactional control?
Here are some more details:
We have one access user that has write access (shared by a very limited number of users - currently only me as the others are on vacation).
We have another access user that is used by many people that only has read access.
Some changes to the data are made by the write user.
After leaving and re-entering the table and/or even the application, the changes seem to have been "committed".
After a while (usually overnight) the changes are lost and the data is back to the old values.
What can cause this behavior?
Our theory is that this is caused by some weird transactional control within Access. The read-only user gets some kind of "exclusive lock" to the data that is used within a query or form. Once the user leaves that query/form, Access makes sure that this is still in the database. If in the meantime the write user has changed the data, these changes will be reverted when the read only user leaves the query/form, resulting in a lost update. Does this make sense? Is this a known issue with MS-Access??
Also, we're interested how we can avoid this issue. Is this something that is inherent in Access and can only be avoided by switching to a "real" database with better transactional control? (From a technical viewpoint, that would be nice; but of course it would be an urgent todo that we would rather avoid at this point in the project.)
Thanks for any input and let me know if there is extra information that is required.
I have seen something slightly similar more than a decade ago, before the bookmark bug was found and patched. In that case, leaving an edited record via bookmark navigation was losing the edit without throwing an error.
In that case, before MS patched it, the solution was to force the save before navigating away from the record:
With Me.RecordsetClone
.FindFirst "..."
If Not .NoMatch Then
If Me.Dirty Then
Me.Dirty = False
End If
Me.Bookmark = .Bookmark
End If
End With
The other thing to check is if error reporting is turned on and how that's interacting with the VBE error handling settings. If the code is littered with On Error Resume Next in order to ignore generated errors, then the code needs to be completely rewritten. The problem with it is that it doesn't always go out of scope as expected.
I never use On Error Resume Next, myself. Instead, if I'm expecting a particular error but want to ignore it, I trap for that error and ignore it, and thus allow any other errors that I haven't anticipated to not disappear down the memory hole.
My thinking here is that some kind of locking issue is generating an error that's being ignored. Thus, the error never gets reported and the changes get lost without anyone ever knowing.
Another thing to look at is whether the back end is stored on a file server where the drives are replicated. This is an untenable setup for Access and Jet, because it completely kills all of Jet/ACE's record locking and internal transactions because the file image is in a state of flux. I've seen reports of what you're describing where two servers were replicated, and both versions of the MDB were being edited. The result was loss of data when the file system replication kicked in and overwrote the changes on one side with the changes from the other.
Your clarification of the scenario is appreciated.
The idea that a read-only user could cause changes by a write user to be lost is not possible.
Maybe the read-only users aren't actually read-only? How, exactly is read-only vs. read/write implemented? In my apps, I'd probably have the forms by default set to read-only, and set Allowedits/Allowadditions/Allowdeletions on the forms to True for the read/write user. I assume from what you've said that you're using Jet user-level security, likely with the default Admin user being the read-only user, and some other user name being the read/write user. Thus, in all the forms you could do this in the OnLoad event:
Me.AllowEdits = (CurrentUser()<>"Admin")
Me.AllowDeletions = Me.AllowEdits
Me.AllowAdditions = Me.AllowEdits
It would also be wise to apply user-level restrictions to the tables (back end only, or both back end and front end), giving read-only Admin user group and User user group, and then give read/write to your one user. Jet ULS is not like NTFS security, where least permissive permissions win -- in Jet ULS, MOST permissive wins, and that's why you have to make sure that you make both Admin and User groups read-only (and give no permissions to the Admin user specifically, i.e., so all permissions are inherited from group membership).
I'm assuming, of course, that this is not being attempted through NTFS permissions on the back-end MDB. If so, that's likely to be a major problem and is simply not the right way to do it. From what you've said, it seems unlikely that this is what is going on, so I won't say any more about it.
But the first thing I'd look at is whether or not the so-called read-only users really are read-only.
Inherited MS Access is always the best,isn't it. To get the obvious solution over and done with early, I recommend moving the data over to SQL Server. It's really not a big job. You might also get some benefit by splitting the database (GUI and data) into separate .mdb's
That all said, I've never come across that sort of behaviour before. Obvious questions are:
How large is the database?
What version is it?
Has it been compacted and repaired recently (take a backup first of course)?
There is transaction processing that you can do with MS Access, but I've found it to be a pain in the butt, and often leads to bizarre errors (until you start grokking the way that the transactions are colliding). Most of your application is probably assuming optimistic locking, and the default behaviour is contradictory to transactions the way you would think of them in Oracle or any other real database. It's probably not worth it.
One more thought, perhaps there's two people with write access looking at the same record at the same time; and one is doing updated in a different field of the record.
Some thoughts:
Is there a genuine need for 2 people to have write access to the same table at the same time? I think you can lock out the 2nd person easily enough by changing the Record Locking and Open Modes in Tools->Options.
You said the updated data usually reverts to its old self at night. Could someone be running an overnight process that also updates the same tables?