2010-04-16 7 views
0

J'ai une certaine logique dans before_save où (seulement) lorsque certaines conditions sont remplies, je laisse la nouvelle ligne être créée avec special_number égal au nombre spécial maximum dans la base de données + 1. (Si les conditions ne sont pas remplies alors je fais quelque chose de différent, donc je ne peux pas utiliser les incréments automatiques)ActiveRecord et les transactions entre `before_save` et` save`

Mon souci est que deux threads agissant sur cette base de données à la fois puissent choisir le même special_number si le second est exécuté pendant que le premier est l'épargne. Est-il possible de verrouiller la base de données entre before_save et terminer la sauvegarde, mais seulement dans certains cas? Je sais que toutes les sauvegardes sont envoyées dans les transactions, cela fera-t-il le travail pour moi?

def before_save 
    if things_are_just_right 
    # -- Issue some kind of lock? 
    # -- self.lock? I have no idea 
    # Pick new special_number 
    new_special = self.class.maximum('special_number') + 1 
    write_attribute('special_number',new_special) 
    else 
    # No need to lock in this case 
    write_attribute('special_number',some_other_number) 
    end 
end 

Répondre

1

Si le numéro spécial est toujours en augmentation de 1, et vous ne pouvez pas avoir des « lacunes », et il est enregistré dans le DB- vous pouvez utiliser select pour la mise à jour:

SELECT special_num FROM nums FOR UPDATE; 
UPDATE nums SET special_num = special_num + 1; 

Vous pouvez lire le ici: select for update

Notez qu'il verrouille le DB, donc vous pouvez avoir un problème de performance si vous avez beaucoup de mises à jour pour un numéro spécial.

Si vous ne vous dérange pas d'avoir des lacunes dans le num spécial (en cas d'une transaction n'a pas) un moyen facile est d'utiliser memcahced fonction « inc », comme il préforme très, très vite :)

+0

Je suis pas réellement en utilisant MySQL! (heroku + sqlite3) - Je ne pense pas que sqlite a une fonction équivalente? –

Questions connexes