2011-12-01 9 views
10

estaba revisando un módulo de Drupal cuando encontré este patrón para obtener el ID de la última fila insertada:¿Es conceptualmente correcto hacer un SELECT MAX (id), etc. para encontrar la última fila insertada?

SELECT MAX(id) FROM ... WHERE ... 

donde el id es un campo de trabajo de una manera habitual incremento automático.

¿Es esto correcto desde el punto de vista conceptual? ¿Hay alguna situación en la que este patrón falle en un entorno MySQL/PostgreSQL?

Editar:

Gracias por los excelentes comentarios y respuestas!

Debo aclarar mi pregunta: me refería a una situación en la que a alguien le gustaría encontrar la identificación de la última fila insertada independientemente de la sesión.

+1

No estoy seguro de conceptualmente bien, pero creo que si la semilla de esa columna se cambia alguna vez, puede que no sea el valor correcto. – user1231231412

+4

Ver [¿Cuál es la forma estándar de obtener la última identificación de inserción?] (Http://stackoverflow.com/questions/5048602/whats-the-stardard-way-of-getting-the-last-insert-id) –

+0

Do te refieres al último registro insertado por la sesión actual? O simplemente un genérico "¿cuál es el registro más nuevo en esta tabla"? Muchas respuestas aquí parecen suponer lo primero, y si ese es el caso, tienen razón. Si el proceso que busca un máximo (id) no busca un proceso de registro ESCRITO insertado, no puedo pensar en un escenario en el que max (id) no proporcione "el registro más reciente en la tabla". – MatBailie

Respuesta

12

Esto parece subjetivo, pero yo diría que no, no es conceptualmente correcto, porque:

  • desea que el más recientemente insertado
  • fila
  • pero la consulta se ve en el máximo valor id

Sí, hay una cierta rela entre la identificación máxima y la inserción más reciente, pero tenga en cuenta lo siguiente:

  • ¿qué ocurre si se eliminó la última fila insertada?

Respuesta en MySQL: obtiene resultados diferentes. Tenga en cuenta que ni siquiera tiene que haber multihilo o múltiples procesos para que esto falle. Eso se debe a que son dos cosas diferentes (que, ciertamente, a menudo puede producir los mismos resultados).

select max(id) from <tablename> 

vs

select last_insert_id() 

(Adivina cuál es el adecuado.)


@Dems señaló que el PO es ambigua.Voy a aclarar mi punto principal:

Estamos hablando de tres diferentes piezas de información:

  • máxima id valor
  • id de la fila más recientemente insertada, específicos para una sesión
  • id de la última fila insertada en la tabla (independientemente de la sesión)

Lo peligroso es que, a veces, consultar uno dará la respuesta correcta para otro: pero no siempre.

+2

Importa si el OP significa encontrar el último registro insertado "por esta sesión", o simplemente el registro más nuevo en la tabla. Es una pregunta fundamentalmente diferente, y no tengo idea de qué pregunta el OP. – MatBailie

0

PostgreSQL que tiene que lidiar con sequences así que todo depende de cómo su configurados

+1

¡DB2 también tiene 'secuencias', que pueden contar hacia atrás! –

2

En MySQL simplemente puede usar LAST_INSERT_ID() que es más garantizado para trabajar.

+3

'last_insert_id()' trabajar solo en la sesión actual supone que USTED tiene agregar valor de incremento automático, otro cliente no verá el nuevo valor por last_insert_id() – triclosan

0

Sin conocer los detalles de su situación particular, diría que esto no es una manera segura. Piense en una situación en la que tiene múltiples clientes insertando registros todo el tiempo. Puedes ponerte en una condición de carrera con consecuencias muy desagradables. Puedes intentar crear un bloqueo, pero eso puede terminar presentando un cuello de botella malo.

+0

Depende de para qué se utiliza esto. Pero no pude resolver una condición de carrera que * importa *. El proceso A comienza a insertar 100 registros, el proceso B comienza a insertar 1 registro, el proceso B es bloqueado por A, su registro siempre tendrá una identificación más alta. De hecho, no puedo crear un escenario en mi cabeza que pueda llevar a que aparezca un registro anterior después de un registro posterior cuando lo ordena una columna de identidad. – MatBailie

1

Depende de la cláusula WHERE y de cómo la aplicación se inserta en esa tabla. SELECT max(ID) FROM table siempre devolverá la ID más grande en el momento en que se ejecuta la consulta. Suponiendo que ID es una clave primaria auto_increment, devolverá la fila más reciente. Sin embargo, en entornos de subprocesos múltiples como servidores web, esa puede no ser la ID que está esperando ya que otro proceso puede haberse insertado también en esa tabla. Por ejemplo, si su código PHP se inserta en la tabla, entonces select max(id) esperando obtener la fila que acaba de insertar, puede que no funcione porque es posible que otro proceso haya insertado otra fila después de que hizo su inserción y antes de que hiciera su select max.

Si el ID es una clave primaria auto_increment (mysql) entonces MySql last_insert_id() o PHP mysql_insert_id() es generalmente una mejor opción. Pero nuevamente, sin conocer la tabla, la cláusula WHERE, o lo que Drupal espera de esta consulta, no es posible decir si Drupal está "haciendo las cosas mal".

5

select max (id) solo se garantiza la recuperación del registro con la ID más alta. puede no ser necesariamente el ÚLTIMO registro insertado en la tabla. Recuerde que las operaciones DB se pueden ejecutar en paralelo. Puede insertar un registro y obtener ID # 5. Pero para el momento en el que se dedica a hacer select MAX(id), alguien más podría haber insertado otro registro y ahora el máximo es realmente # 6 en su lugar.

Además, no puede usarlo para predecir cuál será la próxima identificación asignada. Considere el caso donde se realizan algunos insertos en una transacción. El último registro confirmado en el DB es # 5 nuevamente, luego se realizan 3 inserciones (# 6, # 7, # 8), y luego se retrotraen. La próxima inserción que se realizará en realidad será # 9, no # 6 nuevamente - mysql no recicla los números de identificación de las transacciones fallidas. Y tampoco hay garantía de que USTED obtenga el # 9, alguna otra sesión podría hacer el inserto antes de que lo haga, así que su cuarta inserción podría ser # 10 o # 10,000,000 en su lugar.

1

Leer éste: Directive 595

Epic Fail confiar MAX (id), se produce un error grande.

Cuestiones relacionadas