Generar mi autonumerico

21/05/2008 - 22:02 por CHAR72 | Informe spam
Hola compañeros! tengo cierto inconveniente que no puedo resolver. Tengo un
sistema que tiene un id que lo detemina de una tabla donde guarda el ultimo
id y le va sumando uno por cada nuevo registro. Cuando es un insert de un
registro no hay inconveniente, pero ahora debo realizar varios insert y no
se como obtener ese numero, intente crear una funcion que lo obtenga pero
solo permite otras funciones o procedimientos extendidos.

Como puedo resolver la cuestion con SQL 2000?

Saludos

Carlos

Preguntas similare

Leer las respuestas

#6 Carlos M. Calvelo
23/05/2008 - 11:34 | Informe spam
Hola Miguel,

On May 23, 9:54 am, "Miguel Egea" wrote:
Por problemas de concurrencia.
Verás select max(text) puede ejecutarse a la vez para dos conexiones
distintas y dar el mismo resultado, y el segundo insert fallaría por clave
duplicada ...




Eso solo es verdad si se hace con transacciones con un isolation
level menor que serializable. Entonces dos trasacciones distintas
pueden determinar el max() con el mismo conjunto de registros y
después de que una de ellas haga un insert la otra no se dará
cuenta de una situación de 'phantom read'.

Con isolation level serializable se evitan phantom reads por medio
de locking. Esto a su vez puede resultar en un deadlock que hará
automáticamente un rollback de una de las transacciones y no será
posible obtener el mismo resultado (independientemente de si
con ello se genera un clave duplicada o no).

Saludos,
Carlos
Respuesta Responder a este mensaje
#7 Alfredo Novoa
23/05/2008 - 12:45 | Informe spam
Hola Carlos,

On Fri, 23 May 2008 02:34:03 -0700 (PDT), "Carlos M. Calvelo"
wrote:

Eso solo es verdad si se hace con transacciones con un isolation
level menor que serializable.



Y normalmente se debería de usar el nivel serializable.

Con isolation level serializable se evitan phantom reads por medio
de locking. Esto a su vez puede resultar en un deadlock que hará
automáticamente un rollback de una de las transacciones y no será
posible obtener el mismo resultado (independientemente de si
con ello se genera un clave duplicada o no).



Y además de esto tenemos la protección de las claves primarias. Así
que en el caso de que haya un interbloqueo o una violación de clave
primaria lo único que habría que hacer es repetir la inserción.

Si el nivel de concurrencia no es enorme no hay problema por usar
Max() + 1 para obtener identificadores.


Saludos
Alfredo
Respuesta Responder a este mensaje
#8 Miguel Egea
23/05/2008 - 13:28 | Informe spam
Estais equivocados ambos por que no son lecturas fantasmas, es dificil con
un insert into select max() reproducir el problema pero es muy fácil
reproducirlo de esta forma

probad en 2 conexiones ejecutar este código

set transaction isolation level serializable
go
declare @id int
begin tran

select @id=max(id)+1 from foo
print @id
waitfor delay '00:00:10' -- esperamos 10 segundos
insert into foo select @id
commit



donde los metadatos son

USE tempdb
go
create table foo(id int primary key)
go
insert into foo select 1
go


Hay que tener muchísimo cuidado con la concurrencia,el nivel de aislamiento
serializable es realmente peligroso para el rendimiento, no por el
rendimiento y consumo en sí (que también aunque en un post no me da tiempo a
escribir por qué ese consumo ) sino por los bloqueos, me explico
Un select max() con nivel de aislamiento serializable no solamente bloquea
los registros que ya existen en la tabla sino que genera también un bloqueo
compartido de tipo range que impide que se inserte ningún número mayor, de
aquí el error de mucha gente, que impida que se inserte uno mayor que este
no quiere decir que no le pueda devolver el mismo número a los dos, de hecho
vereis que el segundo en llegar obtiene un error.

Los niveles de aislamiento son un tema muy interesante, si mal no recuerdo
en el Microsoft SQl Server 2005 Step by Step Database Essentials hablé
precisamente de este select max() como herramienta peligrosa en los
sistemas.

Espero que quede claro porqué

Saludos
Miguel Egea


"Alfredo Novoa" wrote in message
news:

Hola Carlos,

On Fri, 23 May 2008 02:34:03 -0700 (PDT), "Carlos M. Calvelo"
wrote:

Eso solo es verdad si se hace con transacciones con un isolation
level menor que serializable.



Y normalmente se debería de usar el nivel serializable.

Con isolation level serializable se evitan phantom reads por medio
de locking. Esto a su vez puede resultar en un deadlock que hará
automáticamente un rollback de una de las transacciones y no será
posible obtener el mismo resultado (independientemente de si
con ello se genera un clave duplicada o no).



Y además de esto tenemos la protección de las claves primarias. Así
que en el caso de que haya un interbloqueo o una violación de clave
primaria lo único que habría que hacer es repetir la inserción.

Si el nivel de concurrencia no es enorme no hay problema por usar
Max() + 1 para obtener identificadores.


Saludos
Alfredo
Respuesta Responder a este mensaje
#9 Miguel Egea
23/05/2008 - 13:33 | Informe spam
Hola Carlos, no suelo comentar cada párrafo de los que me dicen, creo que se
hace dificil de leer, pero como es una opinión personal y tu lo has hecho te
contesto de la misma forma :-). Respetuosamente y siempre hablando desde el
punto de vista técnico estás en un error, espero que te ayude a aclararlo.

Por otra parte, para cualquier neofito que lea este post no me gustaría que
se llevase la idea de que nivel serializable = bueno o adecuado, el nivel de
aislamiento adecuado lo determina el problema que quieras resolver, lo que
hay que hacer es conocerlos todos, poner serializable para usar select max()
en una aplicación me parece un suicidio.

Manejo bases de datos con miles de usuarios concurrentes, y en estos
escenarios el nivel de aislamiento serializables es inviable, simplemente
inviable.

Mis otros comentarios bajo tus lineas


"Carlos M. Calvelo" wrote in message
news:
Hola Miguel,

On May 23, 9:54 am, "Miguel Egea" wrote:
Por problemas de concurrencia.
Verás select max(text) puede ejecutarse a la vez para dos conexiones
distintas y dar el mismo resultado, y el segundo insert fallaría por clave
duplicada ...




Eso solo es verdad si se hace con transacciones con un isolation
level menor que serializable. Entonces dos trasacciones distintas
pueden determinar el max() con el mismo conjunto de registros y
después de que una de ellas haga un insert la otra no se dará
cuenta de una situación de 'phantom read'.
<Miguel Egea>
No, no es cierto, el ejemplo que le he puesto a alfredo lo demuestra, además
no son phantom read, una lectura fantasma solo se puede producir en el nivel
de aislamiento read uncommited, equivocas el concepto.
</Miguel Egea>

Con isolation level serializable se evitan phantom reads por medio
de locking. Esto a su vez puede resultar en un deadlock que hará
automáticamente un rollback de una de las transacciones y no será
posible obtener el mismo resultado (independientemente de si
con ello se genera un clave duplicada o no).
<Miguel Egea>
Te equivocas de nuevo, obtendrás el mismo valor, pero no podrás insertarlo ,
la insercion es lo que provoca el deadloc,
</Miguel Egea>


Saludos,
Carlos
Respuesta Responder a este mensaje
#10 Miguel Egea
23/05/2008 - 13:36 | Informe spam
Hola Alfredo, creo que estas en un error.


El nivel de aislamiento serializalbe lo usaba por defecto las aplicaciones
com+ que accedian a datos y así funcionaban la mayoría que yo he visto, con
enormes problemas de escalabilidad.

Los phantom reads se evitan con todos los nivels de aislamiento menos con
read uncommitted, estáis en un error de concepto de lo que son phantom
reads.

El select max() en otros niveles de aislamiento dará error por Pk, un error
de pk violada es menos agresivo que un deadlock, por que un deadlock además
mata la conexión del elegido como víctima, y además el elegido como vícitma
depende del número de escrituras que lleve en la misma transacción, así que
ni siquiera sabes a priori cual elemento va a resultar eliminado (igual el
listado ese que lleva 2 horas para generarse), excepto que hayas usado la
cŽlausula -escrita de memoria- Set deadlock priority.


Saludos Cordiales..



"Alfredo Novoa" wrote in message
news:

Hola Carlos,

On Fri, 23 May 2008 02:34:03 -0700 (PDT), "Carlos M. Calvelo"
wrote:

Eso solo es verdad si se hace con transacciones con un isolation
level menor que serializable.



Y normalmente se debería de usar el nivel serializable.

Con isolation level serializable se evitan phantom reads por medio
de locking. Esto a su vez puede resultar en un deadlock que hará
automáticamente un rollback de una de las transacciones y no será
posible obtener el mismo resultado (independientemente de si
con ello se genera un clave duplicada o no).



Y además de esto tenemos la protección de las claves primarias. Así
que en el caso de que haya un interbloqueo o una violación de clave
primaria lo único que habría que hacer es repetir la inserción.

Si el nivel de concurrencia no es enorme no hay problema por usar
Max() + 1 para obtener identificadores.


Saludos
Alfredo
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida