How to manage competition between record? - c#

sorry for my bad english. I approached recently to programming in Visual C # and am not a expert programmer. After this short introduction, the important thing I need to implement a management competition on a record during editing operations. This means that having two computers at the same time using this software, the first that starts editing a record, have to "lock" the record so when and if, in the second instance of the program, an attempt to change the same record, a standard message will be displayed and the procedure is interrupted.
I actually use MySQL DBMS and the only thing I could do is to lock the record with "START TRANSACTION" until I COMMIT or close the connection. The problem is that I don't know how to check if there is an active transaction or some kind of block to stop the procedure and this means that the second instance of the program is completely blocked until they release the records from the first instance. Solutions? Thank you for your attention.

Well, in general it's a bad design to physically lock a record while a user is working on it. Database locks are supposed to be short. There should be only code execution between starting the transaction and committing it, but absolutely no user interaction.
You can google "Optimistic locking vs. Pessimistic locking" to understand more about the subject.
If you must use pessimistic locking, you will have to implement some sort of a smart software locks instead of database locks. For example, you could add two fields for the Current_Edit_By and Current_Edit_Time. When a user start editing a record, you fill in these fields with the user id and the current datetime. When another user try editing the same record, you check these two fields and if there are values there then you display an error.
Of course you will need to implement a mechanism to clean locked record automatically if the user disconnect from the database without committing the record. Hence the datetime field (To clear locks older than 30 minutes for example, as long as the connection is no longer there).

Related

Avoiding concurrent access of data in MSSQL

We are developing a C# application that used to work as a single instance application. Now we need to change it to be a multi-user application, meaning the GUI front-end will be run on multiple workstations while accessing a single MS SQL Server 2008 R2 data store.
Part of the work this application manages is queue based, meaning there's a pool of workitems (the list of workitems is in a single SQL table) from which each user can "take" the next available workitem. What I want to accomplish are the following:
once a workitem is "taken" by a user, no other user should have access to it in any way (including reading) until the first user finished working,
handle timeouts (user goes home for the weekend while workitem is taken) and frozen clients (reset button is pressed on the station while workitem is taken).
I know this is a rather general question (much rather a research), so I'm not expecting a detailed solution, but useful links, best practices and/or some literature to read on the subject. Any help is really appreciated since I'm completely lost where to start.
I've seen this done with a transactional resource lock table or column. For example, you assign the record to someone (be it by setting a user ID or some other mechanism) and you simultaneously set a timestamped record as to when that resource was locked. When accessing the data, be it querying it or trying to update it, you first check this lock table/column to make sure it's available. If not, you don't take the changes.
This also supports timeouts then. If the timestamp is too old, the lock is released. You can automatically assumed release if the timestamp is too old, or you can write a scheduled service that will check for expired locks and unlock them. I'd prefer the second way, as it is less costly to check if a lock is there (boolean logic for row exists or if field value exists [i.e. is not null]). But I've seen it done both ways.

Locking of records

I am working on a application where many employees may login to the system to solve customer complaints. If one employee clicks "Start" button for the complain, the record should be freezed. By freezed I mean it should not appear on other employees screen (when the screen updates on their machine using Ajax). Further it shouldn't appear only for a certain amount of time duration. If the employee doesn't response to the complain within few minutes it should again appear in the queue of complaints.
How do I manage this time duration? I have one approach where one the user clicks on "Start", I could store that item in Cache object and it's only valid until it's expiry comes. Then when other employee's screen refreshes I only show those items that are not attended and not present in Cache. If it is present in Cache it means it is being attended by someone. Am I going on the right track? Or is there any better way of doing it?
One thing you could do is have a 'lock' column in the database, and have that column be a DateTime column.
When a user clicks 'Start', note the time in that column.
When retrieving records for display, filter out any which have a non-null value in the lock column, or who's value in the lock column is from at least x minutes ago (which you can calculate using math on the GetDate() function).
The easiest way to do this is to have a column called 'RecordStatus' or something like that, which you can set to a special value to indicate it is still being created or modified.
This forces you to modify all your queries to specifically exclude records that have that status, but in the long term it works better and is more reliable than any type of database or application-level logical locks.
We've solved this at my company in two situations, independently, using some variation on a "record lock" DB record. In one system the locking record is created when the record enters the "queue" as a new item; in the other, the locking record is created when a user picks up a record out of the queue.
Either way you slice it, as of when a user's copy of your software opens a queue record for work, a locking record should be in the DB with some uniquely identifying information about your user written to it. It should be unique to the record being locked, and maybe the lock level (meaning two locks of the same level cannot exist on the same record), and identifies the user who opened the record as "owning" it for the purposes of making changes. This locking record should persist as long as the user has the record open in his software.
The ability to "break" locks can be achieved by simply reassigning the lock to another user, coupled with regular polling of the locking object by the original locking user's software; if, at any time, the user no longer is the owner, the lock has been "broken" and the user has the option to reacquire the lock (breaking the other user's new lock) or simply move on.
Now, should the user's software crash, they will still own a lock on the record. It may also happen that the operation to remove the lock fails (this can happen in situations where the real data is in another DB and you cannot enforce a universal transaction). In such a case, you will need some mechanism to remove "orphaned" locks, or force the user to remove them. If the items being locked are time-sensitive, you will need to design multiple redundant levels of lock removal (perhaps a timed job that, once a minute, will break any lock older than X minutes or which is known to be "orphaned" because that user isn't logged in anymore).

What's the best way to manage concurrency in a database access application?

A while ago, I wrote an application used by multiple users to handle trades creation.
I haven't done development for some time now, and I can't remember how I managed the concurrency between the users. Thus, I'm seeking some advice in terms of design.
The original application had the following characteristics:
One heavy client per user.
A single database.
Access to the database for each user to insert/update/delete trades.
A grid in the application reflecting the trades table. That grid being updated each time someone changes a deal.
I am using WPF.
Here's what I'm wondering:
Am I correct in thinking that I shouldn't care about the connection to the database for each application? Considering that there is a singleton in each, I would expect one connection per client with no issue.
How can I go about preventing the concurrency of the accesses? I guess I should lock when modifying the data, however don't remember how to.
How do I set up the grid to automatically update whenever my database is updated (by another user, for example)?
Thank you in advance for your help!
Consider leveraging Connection Pooling to reduce # of connections. See: http://msdn.microsoft.com/en-us/library/8xx3tyca.aspx
lock as late as possible and release as soon as possible to maximize concurrency. You can use TransactionScope (see: http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx and http://blogs.msdn.com/b/dbrowne/archive/2010/05/21/using-new-transactionscope-considered-harmful.aspx) if you have multiple db actions that need to go together to manage consistency or just handle them in DB stored proc. Keep your query simple. Follow the following tips to understand how locking work and how to reduce resource contention and deadlock: http://www.devx.com/gethelpon/10MinuteSolution/16488
I am not sure other db, but for SQL, you can use SQL Dependency, see http://msdn.microsoft.com/en-us/library/a52dhwx7(v=vs.80).aspx
Concurrency is usually granted by the DBMS using locks. Locks are a type of semaphore that grant the exclusive lock to a certain resource and allow other accesses to be restricted or queued (only restricted in the case you use uncommited reads).
The number of connections itself does not pose a problem while you are not reaching heights where you might touch on the max_connections setting of your DBMS. Otherwise, you might get a problem connecting to it for maintenance purposes or for shutting it down.
DBMSes usually use a concept of either table locks (MyISAM) or row locks (InnoDB, most other DBMSes). The type of lock determines the volume of the lock. Table locks can be very fast but are usually considered inferior to row level locks.
Row level locks occur inside a transaction (implicit or explicit). When manually starting a transaction, you begin your transaction scope. Until you manually close the transaction scope, all changes you make will be attributes to this exact transaction. The changes you make will also obey the ACID paradigm.
Transaction scope and how to use it is a topic far too long for this platform, if you want, I can post some links that carry more information on this topic.
For the automatic updates, most databases support some kind of trigger mechanism, which is code that is run at specific actions on the database (for instance the creation of a new record or the change of a record). You could post your code inside this trigger. However, you should only inform a recieving application of the changes, not really "do" the changes from the trigger, even if the language might make it possible. Remember that the action which triggered the code is suspended until you finish with your trigger code. This means that a lean trigger is best, if it is needed at all.

Prevent duplicate editing / Locking DB records while editing - single backend server

Situation: multiple front-ends (e.g. Silverlight, ASP) sharing a single back-end server (WCF RIA or other web service).
I am looking for a standard to prevent multiple people from editing the same form. I understand that this is not an easy topic, but requirements are requirements.
Previously I used the DB last modified date against the submitted data and give a warning or error if the data was modified since it was loaded. The initial system simply overrode the data without any warning. The problem is that I have a new requirement to prevent both these situations. There will be many UIs, so a locking system might be a challenge, and there is obviously no guarantee that the client will not close the window/browser in the middle of an edit.
I would appreciate any help.
If I'm correct, it seems what you are talking about is a form of check-out/edit/check-in style workflow. You want when one user is editing a record, no other users can even begin to edit the same record.
This is a form of pessimistic concurrency. Many web and data access frameworks have support for (the related) optimistic concurrency - that is, they will tell you that someone else already changed the record when you tried to save. Optimistic has no notion of locking, really - it makes sure that no other user saved between the time you fetched and the time you save.
What you want is not an easy requirement over the web, since the server really has no way to enforce the check-in when a user aborts an edit (say, by closing the browser). I'm not aware of any frameworks that handle this in general.
Basically what you need is to hold checkout information on the server. A user process when editing would need to request a checkout, and the server would grant/deny this based on what they are checking out. The server would also have to hold the information that the resource is checked out. When a user saves the server releases the lock and allows a new checkout when requested. The problem comes when a user aborts the edit - if it's through the UI, no problem... just tell the server to release the lock.
But if it is through closing the browser, powering off the machine, etc then you have an orphaned lock. Most people solve this one of two ways:
1. A timeout. The lock will eventually be released. The upside here is that it is fairly easy and reliable. The downsides are that the record is locked for a while where it's not really in edit. And, you must make your timeout long enough that if the user takes a really, really long time to save they don't get an error because the lock timed out (and they have to start over).
2. A heartbeat. The user has a periodic ping back to the server to say "yep, still editing". This is basically the timeout option from #1, but with a really short timeout that can be refreshed on demand. The upside is that you can make it arbitrarily short. The downside is increased complexity and network usage.
Checkin/checkout tokens are really not that hard to implement if you already have a transacted persistant store (like a DB): the hard part is integrating it into your user experience.

NHibernate session management?

Firstly, let me give a brief description of the scenario. I'm writing a simple game where pretty much all of the work is done on the server side with a thin client for players to access it. A player logs in or creates an account and can then interact with the game by moving around a grid. When they enter a cell, they should be informed of other players in that cell and similarly, other players in that cell will be informed of that player entering it. There are lots of other interactions and actions that can take place but it's not worth going in to detail on them as it's just more of the same. When a player logs out then back in or if the server goes down and comes back up, all of the game state should persist, although if the server crashes, it doesn't matter if I lose 10 minutes or so of changes.
I've decided to use NHibernate and a SQLite database, so I've been reading up a lot on NHibernate, following tutorials and writing some sample applications, and am thoroughly confused as to how I should go about this!
The question I have is: what's the best way to manage my sessions? Just from the small amount that I do understand, all these possibilities jump out at me:
Have a single session that's always opened that all clients use
Have a single session for each client that connects and periodically flush it
Open a session every time I have to use any of the persisted entities and close it as soon as the update, insert, delete or query is complete
Have a session for each client, but keep it disconnected and only reconnect it when I need to use it
Same as above, but keep it connected and only disconnect it after a certain period of inactivity
Keep the entities detached and only attach them every 10 minutes, say, to commit the changes
What kind of strategy should I use to get decent performance given that there could be many updates, inserts, deletes and queries per second from possibly hundreds of clients all at once, and they all have to be consistent with each other?
Another smaller question: how should I use transactions in an efficient manner? Is it fine for every single change to be in its own transaction, or is that going to perform badly when I have hundreds of clients all trying to alter cells in the grid? Should I try to figure out how to bulk together similar updates and place them within a single transaction, or is that going to be too complicated? Do I even need transactions for most of it?
I would use a session per request to the server, and one transaction per session. I wouldn't optimize for performance before the app is mature.
Answer to your solutions:
Have a single session that's always opened that all clients use: You will have performance issues here because the session is not thread safe and you will have to lock all calls to the session.
Have a single session for each client that connects and periodically flush it: You will have performance issues here because all data used by the client will be cached. You will also see problems with stale data from the cache.
Open a session every time I have to use any of the persisted entities and close it as soon as the update, insert, delete or query is complete: You won't have any performance problems here. A disadvantage are possible concurrency or corrupt data problems because related sql statements are not executed in the same transaction.
Have a session for each client, but keep it disconnected and only reconnect it when I need to use it: NHibernate already has build-in connection management and that is already very optimized.
Same as above, but keep it connected and only disconnect it after a certain period of inactivity: Will cause problems because the amount of sql connections is limited and will also limit the amount of users of your application.
Keep the entities detached and only attach them every 10 minutes, say, to commit the changes: Will cause problems because of stale data in the detached entities. You will have to track changes yourself, which makes you end up with a piece of code that looks like the session itself.
It would be useless to go into more detail now, because I would just repeat the manuals/tutorials/book. When you use a session per request, you probably won't have problems in 99% of the application you describe (and maybe not at all). Session is a lightweight not threadsafe class, that to live a very short. When you want to know exactly how the session/connection/caching/transaction management works, I recommend to read a manual first, and than ask some more detailed questions about the unclear subjects.
Read the 'ISessionFactory' on this page of NHibernate documentation. ISessions are meant to be single-threaded (i.e., not thread-safe) which probably means that you shouldn't be sharing it across users. ISessionFactory should be created once by your application and ISessions should be created for each unit of work. Remember that creating an ISessions does not necessarily result in opening a database connection. That depends on how your SessionFactory's connection pooling strategy is configured.
You may also want to look at Hibernate's Documentation on Session and Transaction.
I would aim to keep everything in memory, and either journal changes or take periodic offline snapshots.
Have a read through NHibernate Best Practices with ASP.NET, there are some very good tips in here for a start. As mentioned already be very careful with an ISession as it is NOT threadsafe, so just keep that in mind.
If you require something a little more complex then take a look into the NHibernate.Burrow contrib project. It states something like "the real power Burrow provides is that a Burrow conversation can span over multiple http requests".

Categories