Greetings all, I have a model which holds a counter field, the field have to be incremented frequently to record the access frequency of the specific object: @obj = Temp.find(id) @obj.counter += 1 @obj.save The implementation seems quite simple, but I am worrying about the race condition (if there are any, I do not know whether rails is thread-safe) since these statements may be interleaved. Could anyone help about this? Thanks very much! Difei -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
On Wed, Sep 10, 2008 at 11:59 AM, Difei Zhao <rails-mailing-list-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote:> > Greetings all, > > I have a model which holds a counter field, the field have to be > incremented frequently to record the access frequency of the specific > object: > > @obj = Temp.find(id) > @obj.counter += 1 > @obj.save > > The implementation seems quite simple, but I am worrying about the > race condition (if there are any, I do not know whether rails is > thread-safe) since these statements may be interleaved. Could anyone > help about this? Thanks very much! > > DifeiYou''re correct to worry about a race condition, but for the wrong reason. Rails deployments up to now and for a while yet into the future are clusters of mongrels / thins / etc, and as such nothing is threaded. The race condition in who (as in, which Mongrel) gets to save to the database first. As for protecting against this, you''ll need to make sure to lock the row you working with, update the counter, save, then unlock. You''ll want to do this as quick as possible of course, but it still could cause some slowdown if a lot of processes are trying to do the same thing. If there are better ways around this, I''d definitely be interested in hearing them. Jason --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
You should be doing it like this: Temp.increment_counter( :counter, id ) This will increment the property ":counter" for the model Temp with "id", this column must have a default value of 0 (zero) or else this call won''t work. On Wed, Sep 10, 2008 at 12:59 PM, Difei Zhao <rails-mailing-list-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote:> > Greetings all, > > I have a model which holds a counter field, the field have to be > incremented frequently to record the access frequency of the specific > object: > > @obj = Temp.find(id) > @obj.counter += 1 > @obj.save > > The implementation seems quite simple, but I am worrying about the > race condition (if there are any, I do not know whether rails is > thread-safe) since these statements may be interleaved. Could anyone > help about this? Thanks very much! > > Difei > -- > Posted via http://www.ruby-forum.com/. > > > >-- Maurício Linhares http://alinhavado.wordpress.com/ (pt-br) | http://blog.codevader.com/ (en) João Pessoa, PB, +55 83 8867-7208 --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Maurício Linhares wrote:> You should be doing it like this: > > Temp.increment_counter( :counter, id ) > > This will increment the property ":counter" for the model Temp with > "id", this column must have a default value of 0 (zero) or else this > call won''t work.Thanks a lot! This look like what I am looking for.> > On Wed, Sep 10, 2008 at 12:59 PM, Difei Zhao > <rails-mailing-list-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote: >> >> > -- > Maur�cio Linhares > http://alinhavado.wordpress.com/ (pt-br) | http://blog.codevader.com/ > (en) > Jo�o Pessoa, PB, +55 83 8867-7208-- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
On 10 Sep 2008, at 17:04, Maurício Linhares wrote:> > You should be doing it like this: > > Temp.increment_counter( :counter, id ) > > This will increment the property ":counter" for the model Temp with > "id", this column must have a default value of 0 (zero) or else this > call won''t work.this works because it does update foos set counter = counter + 1 and then it''s the databases problem to worry about concurrent queries and so on. If what you showed was a simplification of what you''re actually doing (and you can''t reduce it to increment_counter) then you''ll need to look into locking (either optimistic or pessimistic) Fred> > > On Wed, Sep 10, 2008 at 12:59 PM, Difei Zhao > <rails-mailing-list-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote: >> >> Greetings all, >> >> I have a model which holds a counter field, the field have to be >> incremented frequently to record the access frequency of the specific >> object: >> >> @obj = Temp.find(id) >> @obj.counter += 1 >> @obj.save >> >> The implementation seems quite simple, but I am worrying about the >> race condition (if there are any, I do not know whether rails is >> thread-safe) since these statements may be interleaved. Could anyone >> help about this? Thanks very much! >> >> Difei >> -- >> Posted via http://www.ruby-forum.com/. >> >>> >> > > > > -- > Maurício Linhares > http://alinhavado.wordpress.com/ (pt-br) | http:// > blog.codevader.com/ (en) > João Pessoa, PB, +55 83 8867-7208 > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Jason Roelofs wrote:> On Wed, Sep 10, 2008 at 11:59 AM, Difei Zhao > <rails-mailing-list-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote: >> >> The implementation seems quite simple, but I am worrying about the >> race condition (if there are any, I do not know whether rails is >> thread-safe) since these statements may be interleaved. Could anyone >> help about this? Thanks very much! >> >> Difei > > You''re correct to worry about a race condition, but for the wrong > reason. Rails deployments up to now and for a while yet into the > future are clusters of mongrels / thins / etc, and as such nothing is > threaded. The race condition in who (as in, which Mongrel) gets to > save to the database first. As for protecting against this, you''ll > need to make sure to lock the row you working with, update the > counter, save, then unlock. You''ll want to do this as quick as > possible of course, but it still could cause some slowdown if a lot of > processes are trying to do the same thing. > > If there are better ways around this, I''d definitely be interested in > hearing them.Maurício proposed the increment_counter method, may I assume that is atomic?> > Jason-- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
On Wed, Sep 10, 2008 at 1:42 PM, Difei Zhao <rails-mailing-list-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote:> Maurício proposed the increment_counter method, may I assume that is > atomic?This method does something like this: "update model_table_name set counter_column = counter_column + 1 where id = ''your row id'' " So, it''s up to your database (and the isolation level that it''s using) to handle the atomicity of this call. Put simply, it will usually work, unless your database has some serious concurrency issues. -- Maurício Linhares http://alinhavado.wordpress.com/ (pt-br) | http://blog.codevader.com/ (en) João Pessoa, PB, +55 83 8867-7208 --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Maurício Linhares wrote:> On Wed, Sep 10, 2008 at 1:42 PM, Difei Zhao > <rails-mailing-list-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote: >> Maur�cio proposed the increment_counter method, may I assume that is >> atomic? > > This method does something like this: > > "update model_table_name set counter_column = counter_column + 1 where > id = ''your row id'' " > > So, it''s up to your database (and the isolation level that it''s using) > to handle the atomicity of this call. > > Put simply, it will usually work, unless your database has some > serious concurrency issues.yeah, as you and Fred said, I noticed the SQL UPDATE statement in the log.> > -- > Maur�cio Linhares > http://alinhavado.wordpress.com/ (pt-br) | http://blog.codevader.com/ > (en) > Jo�o Pessoa, PB, +55 83 8867-7208-- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
One thing to notice is that a loaded model WILL NOT be updated by this call, if you have a model loaded and call this method to perform the increment, the model that is already loaded will not be updated, you will have to call "reload" on it to get the latest counter value. On Wed, Sep 10, 2008 at 1:53 PM, Difei Zhao <rails-mailing-list-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote:> yeah, as you and Fred said, I noticed the SQL UPDATE statement in the > log.-- Maurício Linhares http://alinhavado.wordpress.com/ (pt-br) | http://blog.codevader.com/ (en) João Pessoa, PB, +55 83 8867-7208 --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Maurício Linhares wrote:> One thing to notice is that a loaded model WILL NOT be updated by this > call, if you have a model loaded and call this method to perform the > increment, the model that is already loaded will not be updated, you > will have to call "reload" on it to get the latest counter value.Thanks for the information.> > On Wed, Sep 10, 2008 at 1:53 PM, Difei Zhao > <rails-mailing-list-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote: >> yeah, as you and Fred said, I noticed the SQL UPDATE statement in the >> log. > > > -- > Maur�cio Linhares > http://alinhavado.wordpress.com/ (pt-br) | http://blog.codevader.com/ > (en) > Jo�o Pessoa, PB, +55 83 8867-7208-- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---