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?
Related
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 !
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.
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.
what is the reason that ms-access DBs sometimes has corruption issues?
if a form is not opening and it is a corruption issue, would i solve the problem by eliminating the form?
Someone emailed me this very question yesterday, and I answered them thus:
Have a look at my answers on SO that touch on the issue of corruption as well as these valuable articles by Tony Toews:
Best Practices
Corruption FAQ
There are a number of types of corruption and avoiding different
types requires different solutions. I cover most of those in my SO
answers, while other issues are touched on in Tony's articles.
Specifically, memo pointer corruption is one type, while VBA project corruption is another. Most people aren't referring to either of those when they mention Access/Jet/ACE corruption, though.
Access can handle multi-user scenarios to some degree, but that's definitely not one of its strengths -- even though it's designed to support it, to me the support for multiple users feels "bolted on", and i see plenty of cases where multiple users accessing the same database could corrupt it (or at least, leave the data inconsistent). This is an inherent problem with nearly all client-side DBs, not just Access, but for some reason i hear about far more issues with Access than with other DBs. For single users, i don't think i've ever seen this problem, but i guess it's possible if Access gets killed (or crashes) while it's in the middle of an update, or possibly if you manage to copy the database while Access is still open (which could conceivably get you a corrupted copy).
Probably not. Unless it's the form itself that's corrupted, which seems rather unlikely.
You should take backup of database on regular basis, and use Compact and Repair command to remove errors on daily basis. It is the only way to save your multi user access ms database from being corrupted.
We're thinking of "growing" a little MS-Access DB with a few tables, forms and queries for multiple users. (Using a different back-end is another, but more long-term option that is unfortunately currently not acceptable.)
Most users will be read-only, but there will be a few (currently one or two) users that have to be able to do changes (while the read-only users are also using the DB). We're not so much concerned about the security aspects, but more about some of the following issues:
How can we make sure that the write-user can make changes to the table data while other users use the data? Do the read-users put locks on tables? Does the write-user have to put locks on the table? Does Access do this for us or do we have to explicitly code this?
Are there any common problems with "MS Access transactions" that we should be aware of?
Can we work on forms, queries etc. while they are being used? How can we "program" without being in the way of the users?
Which settings in MS Access have an influence on how things are handled?
Our background is mostly in Oracle, where is Access different in handling multiple users? Is there such thing as "isolation levels" in Access?
Any tips or pointers to helpful articles would be greatly appreciated.
I find the answers to this question to be problematic, confusing and incomplete, so I'll make an effort to do better.
Q1: How can we make sure that the write-user can make changes to the table data while other users use the data? Do the read-users put locks on tables? Does the write-user have to put locks on the table? Does Access do this for us or do we have to explicitly code this?
Nobody has really answered this in any complete fashion. The information on setting locks in the Access options has nothing to do with read vs. write locking. No Locks vs. All Records vs. Edited Record is how you set the default record locking for WRITES.
No locks means you are using OPTIMISTIC locking, which means you allow multiple users to edit the record and then inform them after the fact if the record has changed since they launched their own edits. Optimistic locking is what you should start with as it requires no coding to implement it, and for small users populations it hardly ever causes a problem.
All Records means that the whole table is locked any time an edit is launched.
Edited Record means that fewer records are locked, but whether or not it's a single record or more than one record depends on whether your database is set up to use record-level locking (first added in Jet 4) or page-level locking. Frankly, I've never thought it worth the trouble to set up record-level locking, as optimistic locking takes care of most of the problems.
One might think that you want to use record-level pessimistic locking, but the fact is that in the vast majority of apps, two users are almost never editing the same record. Now, obviously, certain kinds of apps might be exceptions to that, but if I ran into such an app, I'd likely try to engineer it away by redesigning the schema so that it would be very uncommon for two users to edit the same record (usually by going to some form of transactional editing instead, where changes are made by adding records, rather than editing the existing data).
Now, for your actual question, there are a number of ways to accomplish restricting some users to read-only and granting others write privileges. Jet user-level security was intended for this purpose and works fine insofar as it's "security" for any meaningful definition of the term. In general, as long as you're using a Jet/ACE data store, the best security you're going to get is that provided by Jet ULS. It's crackable, yes, but your users would be committing a firable offense by breaking it, so it might be sufficient.
I would tend to not implement Jet ULS at all and instead just architect the data editing forms such that they checked the user's Windows logon and made the forms read-only or writable depending on which users are supposed to get which access. Whether or not you want to record group membership in a data table, or maintain Windows security groups for this purpose is up to you. You could also use a Jet workgroup file to deal with it, and provide a different system.mdw file for the write users. The read-only users would log on transparently as admin, and those logged on as admin would be granted only read-only access. The write users would log on as some other username (transparently, in the shortcut you provide them for launching the app, supplying no password), and that would be used to set up the forms as read or write.
If you use Jet ULS, it can become really hairy to get it right. It involves locking down all the tables as read-only (or maybe not even that) and then using RWOP queries to provide access to the data. I haven't done but one such app in my 14 years of professional Access development.
To summarize my answers to the parts of your question:
How can we make sure that the write-user can make changes to the table data while other users use the data?
I would recommend doing this in the application, setting forms to read/only or editable at runtime depending on the user logon. The easiest approach is to set your forms to be read-only and change to editable for the write users when they open the form.
Do the read-users put locks on tables?
Not in any meaningful sense. Jet/ACE does have read locks, but they are there only for the purpose of maintaining state for individual views, and for refreshing data for the user. They do not lock out write operations of any kind, though the overhead of tracking them theoretically slows things down. It's not enough to worry about.
Does the write-user have to put locks on the table?
Access in combination with Jet/ACE does this for you automatically, particularly if you choose optimistic locking as your default. The key point here is that Access apps are databound, so as soon as a form is loaded, the record has a read lock, and as soon as the record is edited, whether or not it is write-locked for other users is determined by whether you are using optimistic or pessimistic locking. Again, this is the kind of thing Access takes care of for you with its default behaviors in bound forms. You don't worry about any of it until the point at which you encounter problems.
Does Access do this for us or do we have to explicitly code this?
Basically, other than setting editability at runtime (according to who has write access), there is no coding necessary if you're using optimistic locking. With pessimistic locking, you don't have to code, but you will almost always need to, as you can't just leave the user stuck with the default behaviors and error messages.
Q2: Are there any common problems with "MS Access transactions" that we should be aware of?
Jet/ACE has support for commit/rollback transactions, but it's not clear to me if that's what you mean in this question. In general, I don't use transactions except for maintaining atomicity, e.g., when creating an invoice, or doing any update that involves multiple tables. It works about the way you'd expect it to but is not really necessary for the vast majority of operations in an Access application.
Perhaps one of the issues here (particularly in light of the first question) is that you may not quite grasp that Access is designed for creating apps with data bound to the forms. "Transactions" is a topic of great importance for unbound and stateless apps (e.g., browser-based), but for data bound apps, the editing and saving all happens transparently.
For certain kinds of operations this can be problematic, and occasionally it's appropriate to edit data in Access with unbound forms. But that's very seldom the case, in my experience. It's not that I don't use unbound forms -- I use lots of them for dialogs and the like -- it's just that my apps don't edit data tables with unbound forms. With almost no exceptions, all my apps edit data with bound forms.
Now, unbound forms are actually fairly easy to implement in Access (particularly if you name your editing controls the same as the underlying fields), but going with unbound data editing forms is really missing the point of using Access, which is that the binding is all done for you. And the main drawback of going unbound is that you lose all the record-level form events, such as OnInsert, BeforeUpdate and so forth.
Q3. Can we work on forms, queries etc. while they are being used? How can we "program" without being in the way of the users?
This is one of the questions that's been well-addressed. All multi-user or replicated Access apps should be split, and most single-user apps should be, too. It's good design and also makes the apps more stable, as only the data tables end up being opened by more than one user at a time.
Q4. Which settings in MS Access have an influence on how things are handled?
"Things?" What things?
Q5. Our background is mostly in Oracle, where is Access different in handling multiple users? Is there such thing as "isolation levels" in Access?
I don't know anything specifically about Oracle (none of my clients could afford it even if they wanted to), but asking for a comparison of Access and Oracle betrays a fundamental misunderstanding somewhere along the line.
Access is an application development tool.
Oracle is an industrial strength database server.
Apples and oranges.
Now, of course, Access ships with a default database engine, originally called Jet and now revised and renamed ACE, but there are many levels at which Access the development platform can be entirely decoupled from Jet/ACE, the default database engine.
In this case, you've chosen to use a Jet/ACE back end, which will likely be just fine for small user populations, i.e., under 25. Jet/ACE can also be fine up to 50 or 100, particularly when only a few of the simultaneous users have write permission. While the 255-user limit in Jet/ACE includes both read-only and write users, it's the number of write users that really controls how many simultaneous users you can support, and in your case, you've got an app with mostly read-only users, so it oughtn't be terribly difficult to engineer a good app that has no problems with the back end.
Basically, I think your Oracle background is likely leading you to misunderstand how to develop in Access, where the expected approach is to bind your forms to recordsources that are updated without any need to write code. Now, for efficiency's sake it's a good idea to bind your forms to subsets of records, rather than to whole tables, but even with an entire table in the recordsource behind a data editing form, Access is going to be fairly efficient in editing Jet/ACE tables (the old myth about pulling the whole table across the wire is still out there) as long your data tables are efficiently indexed.
Record locking is something you mostly shouldn't have any cause to worry about, and one of the reasons for that is because of bound editing, where the form knows what's going on in the back end at all times (well, at intervals about a second apart, the default refresh interval). That is, it's not like a web page where you retrieve a copy of the data and then post your edits back to the server in a transaction completely unconnected to the original data retrieval operation. In a bound environment like Access, the locking file on the back-end data file is always going to be keeping track of the fact that someone has the record open for editing. This prevents a user's edits from stomping on someone else's edits, because Access knows the state and informs the user. This all happens without any coding on the part of the developer and is one of the great advantages of the bound editing model (aside from not having to write code to post the edits).
For all those who are experienced database programmers familiar with other platforms who are coming to Access for the first time, I strongly suggest using Access like an end user. Try out all the point and click features. Run the form and report wizards and check out the results that they produce. I can't vouch for all of them as demonstrating good practices, but they definitely demonstrate the default assumptions behind the way Access is intended to be used.
If you find yourself writing a lot of code, then you're likely missing the point of Access.
The first thing to do (if not already done) is to split your database into a front end (with all the forms/reports etc) and a back end(with all the data). The second thing is to setup version control on the front end.
The way I have done that in a lot of my databases is to have the users run a small “jumper” database to open the main database. This jumper does the following things
• Checks to see if the user has the database on their C drive
• If they do not then install and run
• If they do then check what version they have
• If the version numbers do not match then copy down the latest version
• Open the database
This whole checking process normally takes under half a second. Using this model you can do all your development on a separate database then when you are ready to “release” you just put the new mde up onto the network share and the next time the user opens the jumper the latest version is copied down.
There are also other things to think about in multiuser database and it might be worth checking for the common mistakes such as binding a form to a whole table etc
i think Access is a best choice for your case. But you have to split database, see:
http://accessblog.net/2005/07/how-to-split-database-into-be-and-fe.html
•How can we make sure that the write-user can make changes to the table data while other users use the data? Do the read-users put locks on tables? Does the write-user have to put locks on the table? Does Access do this for us or do we have to explicitly code this?
there are no read locks unless you put them explicitly. Just use "No Locks"
•Are there any common problems with "MS Access transactions" that we should be aware of?
should not be problems with 1-2 write users
•Can we work on forms, queries etc. while they are being used? How can we "program" without being in the way of the users?
if you split database - then no problem to work on FE design.
•Which settings in MS Access have an influence on how things are handled?
What do you mean?
•Our background is mostly in Oracle, where is Access different in handling multiple users? Is there such thing as "isolation levels" in Access?
no isolation levels in access.
BTW, you can then later move data to oracle and keep access frontend, if you have lot of users and big database.
Table or record locking is available in Access during data writes. You can control the Default record locking through Tools | Options | Advanced tab:
No Locks
All Records
Edited Record
You can set this on a form's Record Locks or in your DAO/ADO code for specific needs.
Transactions shouldn't be a problem if you use them correctly.
Best practice: Separate your tables from All your other code. Give each user their own copy of the code file and then share the data file on a network server. Work on a 'test' copy of the code (and a link to a test data file) and then update user's individual code files separately. If you need to make data file changes (add tables, columns, etc), you will have to have all users get out of the application to make the changes.
See other answers for Oracle comparison.
The correct way of building client/server Microsoft Access applications where the data is stored in a RDBMS is to use the Linked Table method. This ensures Data Isolation and Concurrency is maintained between the Microsoft Access client application and the RDBMS data with no additional and unnecessary programming logic and code which makes maintenance more difficult, and adds to development time.
see: http://claysql.blogspot.com/2014/08/normal-0-false-false-false-en-us-x-none.html
Access is a great multi-user database. It has lots of built in features to handle the multi-user situation. In fact, it is so very popular because it is such a great multi-user database. There is an upper limit on how many users can all use the database at the same time doing updates and edits - depending on how knowledgeable the developer is about access and how the database has been designed - anywhere from 20 users to approx 50 users. Some access databases can be built to handle up to 50 concurrent users, while many others can handle 20 or 25 concurrent users updating the database. These figures have been observed for databases that have been in use for several or more years and have been discussed many times on the access newsgroups.
I have found the SMB2 protocol introduced in Vista to lock the access databases.
It can be disabled by the following regedit:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\LanmanServer\Parameters]
"Smb2"=dword:00000000