In my business logic, there is a function that creates a unique value (it is a session id) by a random function.
I have to be sure, that the session id is unique before I store them into database.
So I am generating new session id, until I found one, that is not yet in database.
But there might be a race condition between checking for existing session ids in database and writing it.
The functions for writing and reading in database are using two different connections.
How can I manage this?
I cannot use auto increments, because the next session should not be guessable.
I think you can make this column UNIQUE (add database constraint), try to insert new row and check wheter it will return an error about duplicate value. Considering that duplicates are very rare it's probably the fastest and safest method.
Related
Suppose we have the following situation:
We have 2-3 tables in database with a huge amount of data (let it be 50-100mln of records) and we want to add 2k of new records. But before adding them we need to check our db on duplicates. So if this 2k contains records which we have in our DB we should ignore them. But to find out whether new record is a duplicate or not we need info from both tables (for example we need to make left join).
The idea of solution is: one task or thread create a suitable data for comparison and pushes data into queue (by batches, not record by record), so our queue(or concurrentQueue) is a global variable. The second thread gets batch from queue and look it through. But there's a problem - memory is growing...
How can I clean memory after I've surfed through the batch?
P.S. If smb has another idea how to optimize this process - please describe it...
This is not the specific answer to the question you are asking, because what you are asking, doesn't really make sense to me.
if you are looking to update specific rows:
INSERT INTO tablename (UniqueKey,columnname1, columnname2, etc...)
VALUES (UniqueKeyValue,value1,value2, etc....)
ON DUPLICATE KEY
UPDATE columnname1=value1, columnname2=value2, etc...
If not, simply ignore/remove the update statement.
This would be darn fast, considering, it would use the unique index of whatever field you want to be unique, and just do an insert or update. No need to validate in a separate table or anything.
We are creating a client server application using WPF/C# with SQL. Here we are generating a unique number b checking DB(To get the last maximum number) and with that max value, we are increment '1' and storing the value in DB. At this time another user also working on the same screen and creating unique numbers, in some case the the unique numbers gets duplicated and throws exception.
We found this is a concurrency issue.
Indeed, fetching a number out, adding one, and hoping it still isn't in use is a thread-race and a race between multiple clients - and should be avoided.
Options:
use an IDENTITY column in the database, and let the database generate the value itself during INSERT; the database server knows how to do this safely and reliably
if that isn't possible, you might want to delay this code until you are ready to INSERT so it is all part of a single database operation - and even then, if it isn't in a "serializable transaction" (with key-range read locks, etc), then you would have to loop on "get the max, increment, try to insert but note that we might have lost a race, so only insert if the value doesn't exist - which it might; repeat from start if unsuccessful"
alternatively, you could create the new record when you first need the number (even though the rest of the data isn't available), noting that you might still need the "loop until successful" approach
Frankly, the IDENTITY column approach is the simplest.
Finally, We have follwed Singleton pattern with lock to resolver this issue.
Thanks.
I have a table and it has one of the attribute set as identity. I want to get the value of the identity attribute that would be generated after I enter a value to the database.
I have EmpTable made of EmpID and EmpName. EmpID is set as Identity. I want to fetch the EmpID value before inserting a new row to the database.
I would advise against trying to do this with a table that is set up to use an integer column as the primary key. You will run into concurrency problems if you simply fetch the previous ID and increment it. Instead you should use a GUID (uniqueidentifier in SQL) as your primary key.
This will allow you to generate a new GUID in your code that can safely be saved to the database at a later stage.
http://msdn.microsoft.com/en-us/library/system.guid.newguid.aspx
http://msdn.microsoft.com/en-us/library/ms187942.aspx
Sure the server knows where the auto-increment count is in its sequence, but there is almost nothing useful you can do with that information. Imagine you go to the Post Office and they hand out numbered tickets so they can serve customers in order. Of course you could ask them what the next number they'll give out is, but since anyone can walk in at any time you don't know you'll get that number. If you don't know that you'll get it, you can't do anything with it - e.g. writing it as a reference number on a form would be a mistake.
Depending on what you're trying to do, your two main options are:
Use a client-generated guid as your identifier. This kind of messes up the order so the analogy isn't great, but imagine if each customer who walked in could generate a random number that they are sure would never have been used before. They could use that to fill out forms before taking a number.
Take a number, but do it in a transaction with the other operations. A customer can take a number and use it to fill out some paperwork. If they realize they left their money at home, they just throw everything away and you never call their number.
Why do you think you need this information? Can you use either of these strategies instead?
Before insert new value to table, I need change one field in all rows of that table.
What the best way to do this? in c# code, ore use trigger? if C# can you show me the code?
UPD
*NEW VERSION of Question*
Hello. Before insert new value to table, I need change one field in all rows of that table with specific ID( It is FK to another table).
What the best way to do this? in c# code, ore use trigger? if C# can you show me the code?
You should probably consider changing your design this doesn't sound like it will scale well, i would probably do it with a trigger if it is always required, but if not, id use ExecuteCommand.
var ctx = new MyDataContext();
ctx.ExecuteCommand("UPDATE myTable SET foo = 'bar'");
Looking at your comment on Paul's answer, I feel like I should chime in here. We have a few tables where we need to keep a history of each entry in that table. We implement this by creating a separate table for each. For example, we may have a Comment table, and then a CommentArchive table with a foreign key reference to the CommentId in the Comment table.
A trigger on the Comment table ensures that each time certain fields in the Comment table are updated, the "old" version (which is accessible via the deleted table in the trigger) gets pushed to the CommentArchive table. Obviously, this means several CommentArchive entries may exist for each Comment, but if you're only looking for the "active" comments, you just look in the Comment table. And if you need information about the history of a comment, you can easily use LINQ to SQL to jump from the Comment you're interested in to the CommentArchives that reference it.
Because the triggers we use in the above example only insert a single value into the Archive table for each update, they run very quickly and we get good performance. We had issues recently where I tried making the triggers more complex and we started getting dead-locks with as few as 15 concurrent transactions. So the lesson is that you should make these triggers simple, and make them touch as few rows in as few tables as possible.
I have a forum application using asp.net, c#, sql server and linq to sql. It suffers from multiple inserts, I think when the insert button is pressed but also maybe when the browser is refreshed or back is clicked.
What's the most comprehensive way, or ways to prevent this.
UPDATE:
I currently use response.redirect after inserting text.
I think maybe the correct approach, upon reading the responses, is to disable the button immediately with javascript?
Followed by saving unique value on hidden field (or session?) on the form. Create a field in the db for this value and check this unique value against this field?
Thanks
Assign a UNIQUE cookie or hidden control to each page
Create a UNIQUE field in your table that holds this cookie or control value.
If a record is inserted with the same cookie, the INSERT will fail and you can process (or ignore) this condition.
When I've a page that does inserting or updating I typically do a Response.Redirect to another page after the update is completed, even if you just Response.Redirect to same page. That way if the page is refreshed you aren't re-posting your data.
Note that your problem isnt really specific to your database. You have a problem with multiple browser requests beeing sent, and you must get around that issue. Either use the redirect pattern as stated above by Dave or use Cookie signing
One example can be found here http://aspalliance.com/711_Preventing_Duplicate_Record_Insertion_on_Page_Refresh_or_Postback_of_a_Web_Form
use a primary key or unique constraint, if you can't do that I suggest you use the new MERGE statement which will insert if it doesn't exist or update if it does exists (don't know your business rules so that might not work in your situation) MERGE is SQL Server 2008 and up
Check out this ASP.NET AJAX control called PostBack Ritalin from a fellow SO'r Dave Ward. This could help you with an already tested solution to your javascript disabler idea.
Assign a unique ID in the form for the comment, and record it with the comment in the database. Perform a check on comments with that unique ID before performing your insert if it doesn't exist.
To allow a user to have several replies on a site active at once, you could allocate the token server-side initially, put that into a list of active posting tokens on the session for that user, put it into the hidden field on the comment form, and only allow a form submission to insert into the database if that token is in the list on the session (and remove it from the list on the session after successfully inserting into the database).
This saves you on ever storing the posting token in the database as above, which is a little easier but tatty.
Put a unique index on the natural key of the data to prevent duplicates from being entered. If required put it against all the fields of the table (except any date oriented ones that would receive the system date at the time of the insert or fields used only by the back end such as insertedby which would contain the user id of the person doing the insertion)except the id.
Select a natural primary key from one or more columns of the input data stream. Declare a primary key constraint on the table, using these columns. If you already have a primary key constraint on a surrogate key, and you don't want to remove it, declare a UNIQUE constraint on the natural key instead.
This will cause an error when the application attempts to insert a duplicate row into the table. You will however have to program the app to field the error, and do the right thing.