2010-05-13 13 views
9

En otras palabras, es el enfoque siguiente "cursoring" garantizado para trabajar:¿SQL Server garantiza la inserción secuencial de una columna de identidad?

  1. recuperar filas de DB
  2. guardar el más grande Identificación de los registros devueltos para más adelante, por ejemplo, en LastMax
  3. después, "SELECT * FROM MyTable WHERE Id > {0}", LastMax

Para que eso funcione, tengo que estar seguros de que cada fila no he tenido en el paso 1 tiene un identificador mayor que LastMax. ¿Esto está garantizado, o puedo encontrarme en condiciones de carrera raras?

Respuesta

11

¿Garantizado como absolutamente en ningún caso podría obtener un valor que podría ser menor o igual que el valor máximo actual? No, no hay tal garantía. Dicho esto, las circunstancias bajo las cuales podría suceder ese escenario son limitadas:

  1. Alguien inhabilita la inserción de identidad e inserta un valor.
  2. Alguien reseeds la columna de identidad.
  3. alguien cambia el signo del valor de incremento (es decir, en lugar de 1 se cambia a -1)

Suponiendo que ninguna de estas circunstancias, que están a salvo de las condiciones de carrera, creando una situación en la que el siguiente valor es menor que un valor existente. Dicho esto, no hay garantía de que las filas sean comprometidas en el orden de sus valores de identidad. Por ejemplo:

  1. Abra una transacción, inserte en su tabla una columna de identidad. Digamos que obtiene el valor 42.
  2. Inserte y consigne en la misma tabla otro valor. Digamos que obtiene el valor 43.

Hasta la primera transacción se comete, 43 existe pero 42 no. La columna de identidad simplemente está reservando un valor, no está dictando el orden de las confirmaciones.

+1

1 la segunda parte es exactamente mi pregunta - y por tanto su respuesta es un "no", porque si lo hago mi primera recuperación de entre el veces cuando 43 se cometen y 42 se comprometen, nunca sabré sobre la fila 42 – balpha

+0

@balpha - Correcto. La columna de identidad simplemente reserva valores que se incrementan automáticamente. No proporciona ninguna garantía en cuanto a la secuencia de valores o la secuencia de confirmaciones. Es * probablemente * el caso de que los valores se hayan comprometido en el orden de sus valores de identidad, pero eso es muy diferente de decir que están * garantizados * en ese orden. – Thomas

+0

+1 La posibilidad de transacción es absolutamente correcta, y simplemente no consideré * dos * otras transacciones, la segunda se cometió primero. Estoy borrando mi respuesta. ¡La buena noticia es que finalmente obtengo mi insignia disciplinada! ¡Hurra! –

1

La única vez que se pueden insertar registros que no obtendría sería si alguien activa la inserción de identidad e inserta manualmente un registro en una identificación omitida (o en algunos casos en un número negativo). Esta es una ocurrencia bastante rara y, en general, solo la realizaría un administrador del sistema. Se podría hacer para volver a insertar un registro borrado accidentalmente, por ejemplo.

2

Identidades siempre seguirán el incremento que define la identidad:

[(semilla, incremento)] http://msdn.microsoft.com/en-us/library/aa933196(SQL.80).aspx

que puede ser positivo o negativo IDENTIDAD (usted puede tener que incrementar hacia adelante o hacia atrás). Si configura su identidad para que se incremente hacia adelante, sus valores de identidad siempre serán más grandes que los anteriores, pero puede perder algunos, si revierte un INSERT.

Sí, si configura su incremento de identidad en un valor positivo, su lógica de bucle funcionará.

0

Lo único que garantiza SQL Server es que su columna de IDENTIDAD siempre se incrementará.

cosas a considerar sin embargo:

  1. Si se produce una inserción de fallar, columna de identidad para obtener incrementado de todos modos;
  2. Si ocurre una reversión, la columna IDENTITY no volverá a su valor anterior;

Lo que explica por qué SQL Server no garantiza la INDEPENDENCIA secuencial.

Hay una manera de restablecer una columna de IDENTIDAD de esta manera utilizando el comando DBCC. Pero antes de hacerlo, tenga en cuenta lo siguiente:

  1. Asegúrese de que su columna IDENTIDAD no esté referenciada en ninguna otra tabla, ya que sus claves externas no podrían actualizarse con ella, por lo que grandes problemas se avecinan;
  2. Puede utilizar la instrucción SET IDENTITY_INSERT ON/OFF para que pueda especificar manualmente la IDENTIDAD al INSERTAR una fila (nunca olvide activarla después).

Una columna de IDENTIDAD es uno de los elementos más importantes que nunca se cambiará en DBRM.

Aquí hay un enlace que le ayudarán a: Understanding IDENTITY columns

EDIT: Lo que parece hacer deberá trabajar como columna IDENTITY de LastMax siempre incrementará para cada fila insertada. Entonces:

  1. Selección de filas de la tabla de datos;
  2. Guardando el estado de LastMax;
  3. Seleccionar filas donde Id> LastMax.

3) solo seleccionará las filas donde la columna IDENTIDAD será mayor que LastMax, por lo que se insertará desde que se guardó LastMax.

4

creo que esto puede ir mal en función de la duración de las transacciones Considere la siguiente secuencia de eventos:

  1. Transacción A comienza
  2. Transacción A realiza insertar - Esto crea una nueva entrada en el columna de identidad
  3. La transacción B comienza
  4. La transacción B realiza la inserción - Esto crea una nueva entrada en la columna de identidad
  5. transacción B se compromete
  6. Su código realiza su selecta y ve el valor de identidad de la segunda transacción
  7. Transacción A comete -

La fila insertada por Transacción A nunca será encontrado por su código. No estaba ya comprometido cuando se realizó el paso 6. Y cuando se realiza la siguiente consulta, no se encontrará porque tiene un valor inferior en la columna de identidad del que busca la consulta.

Podría funcionar si se realiza la consulta con un modo read-uncommitted aislamiento

+0

sí, esa es exactamente mi preocupación – balpha

+0

+1 La posibilidad de transacción es absolutamente correcta, y simplemente no consideré * dos * otras transacciones, la segunda se cometió primero. Estoy borrando mi respuesta. –

Cuestiones relacionadas