sql >> Base de Datos >  >> RDS >> PostgreSQL

Subselección de PostgreSQL y ActiveRecord para la condición de carrera

Sus opciones son:

  • Ejecutar en SERIALIZABLE aislamiento. Las transacciones interdependientes se anularán en el compromiso por tener una falla de serialización. Recibirá una gran cantidad de spam de registro de errores y hará muchos reintentos, pero funcionará de manera confiable.

  • Defina un UNIQUE restricción y vuelva a intentarlo en caso de falla, como anotó. Los mismos problemas que arriba.

  • Si hay un objeto principal, puede SELECT ... FOR UPDATE el objeto principal antes de hacer su max consulta. En este caso, SELECT 1 FROM bar WHERE bar_id = $1 FOR UPDATE . Estás usando bar como candado para todos los foo s con ese bar_id . Entonces puede saber que es seguro continuar, siempre que cada consulta que esté haciendo su incremento de contador lo haga de manera confiable. Esto puede funcionar bastante bien.

    Esto todavía hace una consulta agregada para cada llamada, lo cual (según la siguiente opción) es innecesario, pero al menos no envía spam al registro de errores como las opciones anteriores.

  • Usa una mesa de mostrador. Esto es lo que haría. Ya sea en bar , o en una mesa auxiliar como bar_foo_counter , adquiera un ID de fila usando

    UPDATE bar_foo_counter SET counter = counter + 1
    WHERE bar_id = $1 RETURNING counter
    

    o la opción menos eficiente si su marco no puede manejar RETURNING :

    SELECT counter FROM bar_foo_counter
    WHERE bar_id = $1 FOR UPDATE;
    
    UPDATE bar_foo_counter SET counter = $1;
    

    Luego, en la misma transacción , use la fila de contador generada para el number . Cuando confirmas, la fila de la tabla de contador para ese bar_id se desbloquea para la próxima consulta a utilizar. Si retrocede, el cambio se descarta.

Recomiendo el enfoque de contador, usando una mesa auxiliar dedicada para el contador en lugar de agregar una columna a bar . Eso es más limpio de modelar y significa que creas menos actualizaciones en la bar , que puede ralentizar las consultas a bar .