Diego ! porque no quitar la línea que borrar los registros y hacer un update en vez de un insert, ya que las claves que forman el indice no cambian, no deberías tener problema
@blogger_groups.each do |bg| bgbe = BloggerGroupBlogEntry.find( bg.di, @blog_entry.id) bgbe.update_attributes(...) end son dos comandos sql por cada uno, en vez de un insert... .pero si te soluciona el problema de constrains se paga solo... al menos para ganar tiempo y reveer toda la rutina. -- :: nelson :: artesano de software http://netflux.com.ar 2008/4/12 Diego Algorta Casamayou <[EMAIL PROTECTED]>: > Hola amigos. > > Tengo este problemita en manos y antes de hacer chanchadas me gustaría > saber si alguien tiene sugerencias al respecto. Estoy intentando > arreglar un problema en un código hecho por otra gente, y más allá de > que cuesta entenderlo, creo que ya sé qué está pasando. > Lamentablemente por temas de Non-Disclosure Agreements no puedo poner > mucho código acá... pero les explico. > > Cada tanto (especialmente en horas pico) nos aparece en el log del > postgres este error: > PGError: ERROR: duplicate key violates unique constraint > "blogger_group_blog_entries_blogger_group_id_blog_entry_id": > > Ese índice está definido así: > "blogger_group_blog_entries_blogger_group_id_blog_entry_id" UNIQUE, > btree (blogger_group_id, blog_entry_id) > > Este es un ejemplo de insert que dispara ese error: > INSERT INTO blogger_group_blog_entries ("featured", "blocked", > "blogger_group_id", "blog_entry_id", "active", "agent_id") VALUES('f', > 'f', 231, 462217, 't', 51023) > > > Lo que me llamó la atención, es que si uno sigue el código esto no > "debería" suceder nunca. El código en cuestión se ejecuta cuando se > crea o modifica un BlogEntry. Cuando se trata de una modificación, por > cuestiones que no vienen al caso se debe "reconstruir" todos los > BloggerGroupBlogEntry (registros de la tabla > blogger_group_blog_entries) entonces la cosa es más o menos así > (simplificado): > > # Se borran los registros actuales relacionados con este agente y este > blog_entry, . > BloggerGroupBlogEntry.delete_all("agent_id = " + @agent.id.to_s + " > and blog_entry_id = " + @blog_entry.id.to_s) > # Ahora se vuelven a crear los registros uno a uno. Sí, son los mismos > registros en cuanto a ids y relaciones, sólo tienen cambios en campos > NO relevantes al índice único y todo eso. > @blogger_groups.each do |bg| > bgbe = BloggerGroupBlogEntry.new > bgbe.blogger_group_id = bg.id > bgbe.blog_entry_id = @blog_entry.id > bgbe.agent_id = @agent.id > #bgbe ... seteo de otros datos no relevantes ... > bgbe.save > end > > No es código mío... yo sólo trato de arreglar el error... :) > > Entonces, como ven... esto no debería dar clave duplicada, pues los > registros que estoy insertando, primero fueron borrados, y como ya > existían, cumplían la unicidad del índice. > > Ahora viene mi deducción: Este problema sucede casi únicamente en > ocasiones donde el sitio ha estado muy sobrecargado, con varios miles > de usuarios simultáneos usándolo, y con algún problema de performance > en el hardware. En esas ocasiones, los usuarios suelen ser muy > impacientes y hacen el submit del formulario repetidamente... lo cual > ocasiona varios requests con los mismos parámetros ejecutándose al > mismo tiempo. > > Mi teoría es que dos o más requests simultáneos "compiten" por hacer > los MISMOS inserts y el más lento termina intentando insertar > registros que ya otro request insertó. > > ¿qué opinan? > > Más allá de eso... ¿qué sugerencias me pueden dar para evitar este > problema? En lo posible evitando locks gigantes. > > Gracias! > > -- > Diego Algorta Casamayou > http://www.oboxodo.com - http://diego.algorta.net > _______________________________________________ > Ruby mailing list > [email protected] > http://lista.rubyargentina.com.ar/listinfo.cgi/ruby-rubyargentina.com.ar > _______________________________________________ Ruby mailing list [email protected] http://lista.rubyargentina.com.ar/listinfo.cgi/ruby-rubyargentina.com.ar
