Quantcast
Channel: jhjguxin
Viewing all articles
Browse latest Browse all 14

Atomic Increment in Rails

$
0
0
Many times you are put in a situation that you need to increment an ActiveRecord attribute, but you need to make it Atomic to avoid any concurrency problems. Using the ActiveRecord#increment! is not the answer. post.increment! :posts_count the previous code results the following SQL: UPDATE 'posts' SET 'posts_count' = 1 WHERE 'id' = 38 This for sure is not Atomic since there is a read operation for the attribute then incrementing it with ruby then update that field with the new value. The right answer is “increment_counter” . it is a class method that makes a real atomic update . Post.increment_counter :posts_count , 38 take alook at the result SQL: UPDATE 'posts' SET 'posts_count' = COALESCE('posts_count', 0) + 1 WHERE ( 'id'= 38) Clearly it is Atomic and no threat of a concurrency(并发) problem. A side note COALESCE() function is used to return the first not-Null value from the passed array. it is used here to handle the case that this atribute is Null as a Zero. If you need to increment multiple attributes or even increment an attribute with a value other than 1. A very helpful class method is "update_counters" Post.update_counters 38 , :posts_count => 2 , :update_calls_count => 1 The result SQL is UPDATE 'posts' SET 'posts_count' = COALESCE('posts_count', 0) + 2, 'update_calls_count' = COALESCE('update_calls_count', 0) + 1 WHERE ('id' = 38)

Viewing all articles
Browse latest Browse all 14