Duda sobre nivel de aislamiento

08/09/2007 - 12:14 por Vicente Flich | Informe spam
Hola a todos:

Estamos migrando una aplicacion para que trabaje contra un servidor SLQ
Server 2005. La duda es sobre el nivel de aislamiento de las transacciones.
Lo explico con un ejemplo. En la aplicacion gestiona clientes, cada uno
logicamente tiene su codigo de cliente (por ejemplo un campo numerico). Lo
que queremos es que al crear un nuevo cliente se busque el ultimo codigo de
cliente, le sumamos 1 y añadimos el nuevo cliente.

El problema viene cuando se trabaja en multiusuario. Tenemos que evitar que
se creen 2 codigos de cliente iguales.

Para ejemplificarlo, en lugar de poner nuestro codigo en C++, os pongo el
siguiente 'pseudocodigo':

use BASEDEDATOS
set transaction isolation level serializable
begin transaction

// Punto 1: Obtenemos el ultimo registro
select top(1) codigo from clientes order by codigo desc
nuevocodigo = clientes.codigo+1

// Punto 2: Grabamos
insert into clientes (codigo) values(Nuevocodigo)

commit

En el pseudocodigo anterior, si 2 procesos se ejecutan simultaneamente,
ambos ejecutan el Punto1 a la vez... los 2 procesos dan con el mismo codigo,
duplicando el codigo de articulo.

He probado con todos los niveles de aislamiento: READ COMMITTED, UNCOMMITED,
SERIALIZABLE, REPEATABLE READS, SNAPSHOT, pero en todos falla.

Supongo que esto debe hacerse mejor de otra forma (hacer el codigo como
campo identity por ejemplo), pero no me sirve, ya que como os he comentado
estamos migrando una aplicacion (programada al estilo XBase) y es una
aplicacion bastante grande, lo tengo todo migrado a excepcion de este
problema y no es solo al crear un cliente, sino en muhos otros puntos del
programa.

Gracias por adelantado.

Saludos,
Vicente Flich
Flifeca Aplicaciones Informáticas

Preguntas similare

Leer las respuestas

#1 Alejandro Mesa
09/09/2007 - 19:32 | Informe spam
Hola Vicente,

Hay varias maneras de lograr esto.

1 - usar el el hint de tabla (updlock) o (tablelock) en la sentencia que
selecciona
2 - usar una tabla especifica para mantener esta numeración.

Te dejo de tarea leer sobe el primer metodo, y te paso un ejemplo sobre el
segundo.

use mi_db
go

create table dbo.codigo (
nombre_tabla sysname not null primary key,
codigo int not null default(0),
incremento smallint not null default(1)
)
go

insert into dbo.codigo (nombre_tabla, codigo, incremento) values('clientes',
0, 1)
go

create procedure dbo.usp_proximo_codigo
@nombre_table sysname,
@codigo int output
as

set nocount on

update dbo.codigo
set @codigo = codigo = codigo + incremento
where nombre_tabla = @nombre_tabla

return @@error
go

declare @codigo int
declare @rv int
declare @error int
declare @nombre varchar(50)

set @nombre = 'Microsoft'

begin transaction

exec @rv = dbo.usp_proximo_codigo 'clientes', @codigo output

set @error = coalesce(nullif(@rv, 0), @@error)

if @error = 0
begin
insert into dbo.clientes(codigo, nombre) values(@codigo, @nombre)

if @@error != 0
begin
raiserror('error seleccionando proximo codigo.', 16, 1)
goto ErrorHandler
end
end
else
begin
raiserror('error insertando cliente.', 16, 1)
goto ErrorHandler
end

commit transaction

return 0

ErrorHandler:
if @@trancount > 0
rollback transaction

return -1
go

Este codigo lo escribo mientras te respondo, asi que si algo no funciona
entonces dejanos saber.


AMB

"Vicente Flich" wrote:

Hola a todos:

Estamos migrando una aplicacion para que trabaje contra un servidor SLQ
Server 2005. La duda es sobre el nivel de aislamiento de las transacciones.
Lo explico con un ejemplo. En la aplicacion gestiona clientes, cada uno
logicamente tiene su codigo de cliente (por ejemplo un campo numerico). Lo
que queremos es que al crear un nuevo cliente se busque el ultimo codigo de
cliente, le sumamos 1 y añadimos el nuevo cliente.

El problema viene cuando se trabaja en multiusuario. Tenemos que evitar que
se creen 2 codigos de cliente iguales.

Para ejemplificarlo, en lugar de poner nuestro codigo en C++, os pongo el
siguiente 'pseudocodigo':

use BASEDEDATOS
set transaction isolation level serializable
begin transaction

// Punto 1: Obtenemos el ultimo registro
select top(1) codigo from clientes order by codigo desc
nuevocodigo = clientes.codigo+1

// Punto 2: Grabamos
insert into clientes (codigo) values(Nuevocodigo)

commit

En el pseudocodigo anterior, si 2 procesos se ejecutan simultaneamente,
ambos ejecutan el Punto1 a la vez... los 2 procesos dan con el mismo codigo,
duplicando el codigo de articulo.

He probado con todos los niveles de aislamiento: READ COMMITTED, UNCOMMITED,
SERIALIZABLE, REPEATABLE READS, SNAPSHOT, pero en todos falla.

Supongo que esto debe hacerse mejor de otra forma (hacer el codigo como
campo identity por ejemplo), pero no me sirve, ya que como os he comentado
estamos migrando una aplicacion (programada al estilo XBase) y es una
aplicacion bastante grande, lo tengo todo migrado a excepcion de este
problema y no es solo al crear un cliente, sino en muhos otros puntos del
programa.

Gracias por adelantado.

Saludos,
Vicente Flich
Flifeca Aplicaciones Informáticas

Respuesta Responder a este mensaje
#2 Vicente Flich
10/09/2007 - 09:52 | Informe spam
Gracias por la ayuda. La segunda opcion la veo mas clara, pero para una
aplicación nueva. En el caso de mi aplicación veo difícil de aplicar (por
ciercunstancias que no vendrían a cuento).

La solución de bloquear en el select la veo más fácil de incorporar a mi
programa, aunque me da miedo los interbloqueos que pueda generar y como
tratarlos. En fin, lo investigaré.

¿No hay alguna forma de bloquear una tabla sólo para escritura? es decir,
bloquear la tabla para que sólo pueda escribir un proceso, pero que el resto
de procesos pueda seguir leyendo.

Saludos,
Vicente Flich


"Alejandro Mesa" wrote:

Hola Vicente,

Hay varias maneras de lograr esto.

1 - usar el el hint de tabla (updlock) o (tablelock) en la sentencia que
selecciona
2 - usar una tabla especifica para mantener esta numeración.

Te dejo de tarea leer sobe el primer metodo, y te paso un ejemplo sobre el
segundo.

use mi_db
go

create table dbo.codigo (
nombre_tabla sysname not null primary key,
codigo int not null default(0),
incremento smallint not null default(1)
)
go

insert into dbo.codigo (nombre_tabla, codigo, incremento) values('clientes',
0, 1)
go

create procedure dbo.usp_proximo_codigo
@nombre_table sysname,
@codigo int output
as

set nocount on

update dbo.codigo
set @codigo = codigo = codigo + incremento
where nombre_tabla = @nombre_tabla

return @@error
go

declare @codigo int
declare @rv int
declare @error int
declare @nombre varchar(50)

set @nombre = 'Microsoft'

begin transaction

exec @rv = dbo.usp_proximo_codigo 'clientes', @codigo output

set @error = coalesce(nullif(@rv, 0), @@error)

if @error = 0
begin
insert into dbo.clientes(codigo, nombre) values(@codigo, @nombre)

if @@error != 0
begin
raiserror('error seleccionando proximo codigo.', 16, 1)
goto ErrorHandler
end
end
else
begin
raiserror('error insertando cliente.', 16, 1)
goto ErrorHandler
end

commit transaction

return 0

ErrorHandler:
if @@trancount > 0
rollback transaction

return -1
go

Este codigo lo escribo mientras te respondo, asi que si algo no funciona
entonces dejanos saber.


AMB

"Vicente Flich" wrote:

> Hola a todos:
>
> Estamos migrando una aplicacion para que trabaje contra un servidor SLQ
> Server 2005. La duda es sobre el nivel de aislamiento de las transacciones.
> Lo explico con un ejemplo. En la aplicacion gestiona clientes, cada uno
> logicamente tiene su codigo de cliente (por ejemplo un campo numerico). Lo
> que queremos es que al crear un nuevo cliente se busque el ultimo codigo de
> cliente, le sumamos 1 y añadimos el nuevo cliente.
>
> El problema viene cuando se trabaja en multiusuario. Tenemos que evitar que
> se creen 2 codigos de cliente iguales.
>
> Para ejemplificarlo, en lugar de poner nuestro codigo en C++, os pongo el
> siguiente 'pseudocodigo':
>
> use BASEDEDATOS
> set transaction isolation level serializable
> begin transaction
>
> // Punto 1: Obtenemos el ultimo registro
> select top(1) codigo from clientes order by codigo desc
> nuevocodigo = clientes.codigo+1
>
> // Punto 2: Grabamos
> insert into clientes (codigo) values(Nuevocodigo)
>
> commit
>
> En el pseudocodigo anterior, si 2 procesos se ejecutan simultaneamente,
> ambos ejecutan el Punto1 a la vez... los 2 procesos dan con el mismo codigo,
> duplicando el codigo de articulo.
>
> He probado con todos los niveles de aislamiento: READ COMMITTED, UNCOMMITED,
> SERIALIZABLE, REPEATABLE READS, SNAPSHOT, pero en todos falla.
>
> Supongo que esto debe hacerse mejor de otra forma (hacer el codigo como
> campo identity por ejemplo), pero no me sirve, ya que como os he comentado
> estamos migrando una aplicacion (programada al estilo XBase) y es una
> aplicacion bastante grande, lo tengo todo migrado a excepcion de este
> problema y no es solo al crear un cliente, sino en muhos otros puntos del
> programa.
>
> Gracias por adelantado.
>
> Saludos,
> Vicente Flich
> Flifeca Aplicaciones Informáticas
>
Respuesta Responder a este mensaje
#3 Miguel Egea
10/09/2007 - 13:14 | Informe spam
Con el permiso de alejandro

Si estás en 2005 y habilitas el Read_committed_snapshot el hint de bloqueo
de tabla no afectará a los lectores.

Saludos


"Vicente Flich" wrote in message
news:
Gracias por la ayuda. La segunda opcion la veo mas clara, pero para una
aplicación nueva. En el caso de mi aplicación veo difícil de aplicar (por
ciercunstancias que no vendrían a cuento).

La solución de bloquear en el select la veo más fácil de incorporar a mi
programa, aunque me da miedo los interbloqueos que pueda generar y como
tratarlos. En fin, lo investigaré.

¿No hay alguna forma de bloquear una tabla sólo para escritura? es decir,
bloquear la tabla para que sólo pueda escribir un proceso, pero que el
resto
de procesos pueda seguir leyendo.

Saludos,
Vicente Flich


"Alejandro Mesa" wrote:

Hola Vicente,

Hay varias maneras de lograr esto.

1 - usar el el hint de tabla (updlock) o (tablelock) en la sentencia que
selecciona
2 - usar una tabla especifica para mantener esta numeración.

Te dejo de tarea leer sobe el primer metodo, y te paso un ejemplo sobre
el
segundo.

use mi_db
go

create table dbo.codigo (
nombre_tabla sysname not null primary key,
codigo int not null default(0),
incremento smallint not null default(1)
)
go

insert into dbo.codigo (nombre_tabla, codigo, incremento)
values('clientes',
0, 1)
go

create procedure dbo.usp_proximo_codigo
@nombre_table sysname,
@codigo int output
as

set nocount on

update dbo.codigo
set @codigo = codigo = codigo + incremento
where nombre_tabla = @nombre_tabla

return @@error
go

declare @codigo int
declare @rv int
declare @error int
declare @nombre varchar(50)

set @nombre = 'Microsoft'

begin transaction

exec @rv = dbo.usp_proximo_codigo 'clientes', @codigo output

set @error = coalesce(nullif(@rv, 0), @@error)

if @error = 0
begin
insert into dbo.clientes(codigo, nombre) values(@codigo, @nombre)

if @@error != 0
begin
raiserror('error seleccionando proximo codigo.', 16, 1)
goto ErrorHandler
end
end
else
begin
raiserror('error insertando cliente.', 16, 1)
goto ErrorHandler
end

commit transaction

return 0

ErrorHandler:
if @@trancount > 0
rollback transaction

return -1
go

Este codigo lo escribo mientras te respondo, asi que si algo no funciona
entonces dejanos saber.


AMB

"Vicente Flich" wrote:

> Hola a todos:
>
> Estamos migrando una aplicacion para que trabaje contra un servidor SLQ
> Server 2005. La duda es sobre el nivel de aislamiento de las
> transacciones.
> Lo explico con un ejemplo. En la aplicacion gestiona clientes, cada uno
> logicamente tiene su codigo de cliente (por ejemplo un campo numerico).
> Lo
> que queremos es que al crear un nuevo cliente se busque el ultimo
> codigo de
> cliente, le sumamos 1 y añadimos el nuevo cliente.
>
> El problema viene cuando se trabaja en multiusuario. Tenemos que evitar
> que
> se creen 2 codigos de cliente iguales.
>
> Para ejemplificarlo, en lugar de poner nuestro codigo en C++, os pongo
> el
> siguiente 'pseudocodigo':
>
> use BASEDEDATOS
> set transaction isolation level serializable
> begin transaction
>
> // Punto 1: Obtenemos el ultimo registro
> select top(1) codigo from clientes order by codigo desc
> nuevocodigo = clientes.codigo+1
>
> // Punto 2: Grabamos
> insert into clientes (codigo) values(Nuevocodigo)
>
> commit
>
> En el pseudocodigo anterior, si 2 procesos se ejecutan simultaneamente,
> ambos ejecutan el Punto1 a la vez... los 2 procesos dan con el mismo
> codigo,
> duplicando el codigo de articulo.
>
> He probado con todos los niveles de aislamiento: READ COMMITTED,
> UNCOMMITED,
> SERIALIZABLE, REPEATABLE READS, SNAPSHOT, pero en todos falla.
>
> Supongo que esto debe hacerse mejor de otra forma (hacer el codigo como
> campo identity por ejemplo), pero no me sirve, ya que como os he
> comentado
> estamos migrando una aplicacion (programada al estilo XBase) y es una
> aplicacion bastante grande, lo tengo todo migrado a excepcion de este
> problema y no es solo al crear un cliente, sino en muhos otros puntos
> del
> programa.
>
> Gracias por adelantado.
>
> Saludos,
> Vicente Flich
> Flifeca Aplicaciones Informáticas
>
Respuesta Responder a este mensaje
#4 Vicente Flich
17/09/2007 - 08:04 | Informe spam
Gracias Miguel. Al final he optado por la opción que comenta Alejandro. He
puesto el hint tablockx con el nivel de aislamiento serializable, osea:


use BASEDEDATOS
set transaction isolation level serializable
begin transaction

// Punto 1: Obtenemos el ultimo registro
select top(1) codigo from clientes with (tablockx) order by codigo desc
nuevocodigo = clientes.codigo+1

// Punto 2: Grabamos
insert into clientes (codigo) values(Nuevocodigo)
commit

De esta forma, la tabla se queda bloqueada (tanto para procesos lectores
como procesos escritores) hasta que la transaccion se finaliza.

Ahora estoy viendo como gestionar cuando ocurre un interbloqueo, pero eso ya
es otra historia.

Saludos y gracias,

Vicente Flich




"Miguel Egea" wrote:

Con el permiso de alejandro

Si estás en 2005 y habilitas el Read_committed_snapshot el hint de bloqueo
de tabla no afectará a los lectores.

Saludos


"Vicente Flich" wrote in message
news:
> Gracias por la ayuda. La segunda opcion la veo mas clara, pero para una
> aplicación nueva. En el caso de mi aplicación veo difícil de aplicar (por
> ciercunstancias que no vendrían a cuento).
>
> La solución de bloquear en el select la veo más fácil de incorporar a mi
> programa, aunque me da miedo los interbloqueos que pueda generar y como
> tratarlos. En fin, lo investigaré.
>
> ¿No hay alguna forma de bloquear una tabla sólo para escritura? es decir,
> bloquear la tabla para que sólo pueda escribir un proceso, pero que el
> resto
> de procesos pueda seguir leyendo.
>
> Saludos,
> Vicente Flich
>
>
> "Alejandro Mesa" wrote:
>
>> Hola Vicente,
>>
>> Hay varias maneras de lograr esto.
>>
>> 1 - usar el el hint de tabla (updlock) o (tablelock) en la sentencia que
>> selecciona
>> 2 - usar una tabla especifica para mantener esta numeración.
>>
>> Te dejo de tarea leer sobe el primer metodo, y te paso un ejemplo sobre
>> el
>> segundo.
>>
>> use mi_db
>> go
>>
>> create table dbo.codigo (
>> nombre_tabla sysname not null primary key,
>> codigo int not null default(0),
>> incremento smallint not null default(1)
>> )
>> go
>>
>> insert into dbo.codigo (nombre_tabla, codigo, incremento)
>> values('clientes',
>> 0, 1)
>> go
>>
>> create procedure dbo.usp_proximo_codigo
>> @nombre_table sysname,
>> @codigo int output
>> as
>>
>> set nocount on
>>
>> update dbo.codigo
>> set @codigo = codigo = codigo + incremento
>> where nombre_tabla = @nombre_tabla
>>
>> return @@error
>> go
>>
>> declare @codigo int
>> declare @rv int
>> declare @error int
>> declare @nombre varchar(50)
>>
>> set @nombre = 'Microsoft'
>>
>> begin transaction
>>
>> exec @rv = dbo.usp_proximo_codigo 'clientes', @codigo output
>>
>> set @error = coalesce(nullif(@rv, 0), @@error)
>>
>> if @error = 0
>> begin
>> insert into dbo.clientes(codigo, nombre) values(@codigo, @nombre)
>>
>> if @@error != 0
>> begin
>> raiserror('error seleccionando proximo codigo.', 16, 1)
>> goto ErrorHandler
>> end
>> end
>> else
>> begin
>> raiserror('error insertando cliente.', 16, 1)
>> goto ErrorHandler
>> end
>>
>> commit transaction
>>
>> return 0
>>
>> ErrorHandler:
>> if @@trancount > 0
>> rollback transaction
>>
>> return -1
>> go
>>
>> Este codigo lo escribo mientras te respondo, asi que si algo no funciona
>> entonces dejanos saber.
>>
>>
>> AMB
>>
>> "Vicente Flich" wrote:
>>
>> > Hola a todos:
>> >
>> > Estamos migrando una aplicacion para que trabaje contra un servidor SLQ
>> > Server 2005. La duda es sobre el nivel de aislamiento de las
>> > transacciones.
>> > Lo explico con un ejemplo. En la aplicacion gestiona clientes, cada uno
>> > logicamente tiene su codigo de cliente (por ejemplo un campo numerico).
>> > Lo
>> > que queremos es que al crear un nuevo cliente se busque el ultimo
>> > codigo de
>> > cliente, le sumamos 1 y añadimos el nuevo cliente.
>> >
>> > El problema viene cuando se trabaja en multiusuario. Tenemos que evitar
>> > que
>> > se creen 2 codigos de cliente iguales.
>> >
>> > Para ejemplificarlo, en lugar de poner nuestro codigo en C++, os pongo
>> > el
>> > siguiente 'pseudocodigo':
>> >
>> > use BASEDEDATOS
>> > set transaction isolation level serializable
>> > begin transaction
>> >
>> > // Punto 1: Obtenemos el ultimo registro
>> > select top(1) codigo from clientes order by codigo desc
>> > nuevocodigo = clientes.codigo+1
>> >
>> > // Punto 2: Grabamos
>> > insert into clientes (codigo) values(Nuevocodigo)
>> >
>> > commit
>> >
>> > En el pseudocodigo anterior, si 2 procesos se ejecutan simultaneamente,
>> > ambos ejecutan el Punto1 a la vez... los 2 procesos dan con el mismo
>> > codigo,
>> > duplicando el codigo de articulo.
>> >
>> > He probado con todos los niveles de aislamiento: READ COMMITTED,
>> > UNCOMMITED,
>> > SERIALIZABLE, REPEATABLE READS, SNAPSHOT, pero en todos falla.
>> >
>> > Supongo que esto debe hacerse mejor de otra forma (hacer el codigo como
>> > campo identity por ejemplo), pero no me sirve, ya que como os he
>> > comentado
>> > estamos migrando una aplicacion (programada al estilo XBase) y es una
>> > aplicacion bastante grande, lo tengo todo migrado a excepcion de este
>> > problema y no es solo al crear un cliente, sino en muhos otros puntos
>> > del
>> > programa.
>> >
>> > Gracias por adelantado.
>> >
>> > Saludos,
>> > Vicente Flich
>> > Flifeca Aplicaciones Informáticas
>> >


Respuesta Responder a este mensaje
#5 Vicente Flich
19/09/2007 - 23:52 | Informe spam
Alejandro, he estado viendo lo de los hints de tablas. Creo que si que me
sirven, utilizando un nivel de aislamiento SERIALIZABLE y poniendo en el
select el hint WITH(TABLOCKX) con lo que se bloquea la tabla en exclusiva y
el bloqueo se mantiene hasta finalizar la transaccion.

Hasta ahi todo ok, pero he observado que a veces no me bloquea las tablas.
Investigando mas sobre el tema he leido que los hints son sugerencias pero
que puede que al ejecutarse la sentencia select que el SQL no las aplique,
asi que no tendría seguridad de que se bloquea la tabla.

¿Esto es asi o estoy equiocado? En caso de ser así ¿no hay forma de
asegurarme de que se bloquea en exclusiva una tabla ó fila?

Saludos,
Vicente Flich


"Alejandro Mesa" wrote:

Hola Vicente,

Hay varias maneras de lograr esto.

1 - usar el el hint de tabla (updlock) o (tablelock) en la sentencia que
selecciona
2 - usar una tabla especifica para mantener esta numeración.

Te dejo de tarea leer sobe el primer metodo, y te paso un ejemplo sobre el
segundo.

use mi_db
go

create table dbo.codigo (
nombre_tabla sysname not null primary key,
codigo int not null default(0),
incremento smallint not null default(1)
)
go

insert into dbo.codigo (nombre_tabla, codigo, incremento) values('clientes',
0, 1)
go

create procedure dbo.usp_proximo_codigo
@nombre_table sysname,
@codigo int output
as

set nocount on

update dbo.codigo
set @codigo = codigo = codigo + incremento
where nombre_tabla = @nombre_tabla

return @@error
go

declare @codigo int
declare @rv int
declare @error int
declare @nombre varchar(50)

set @nombre = 'Microsoft'

begin transaction

exec @rv = dbo.usp_proximo_codigo 'clientes', @codigo output

set @error = coalesce(nullif(@rv, 0), @@error)

if @error = 0
begin
insert into dbo.clientes(codigo, nombre) values(@codigo, @nombre)

if @@error != 0
begin
raiserror('error seleccionando proximo codigo.', 16, 1)
goto ErrorHandler
end
end
else
begin
raiserror('error insertando cliente.', 16, 1)
goto ErrorHandler
end

commit transaction

return 0

ErrorHandler:
if @@trancount > 0
rollback transaction

return -1
go

Este codigo lo escribo mientras te respondo, asi que si algo no funciona
entonces dejanos saber.


AMB

"Vicente Flich" wrote:

> Hola a todos:
>
> Estamos migrando una aplicacion para que trabaje contra un servidor SLQ
> Server 2005. La duda es sobre el nivel de aislamiento de las transacciones.
> Lo explico con un ejemplo. En la aplicacion gestiona clientes, cada uno
> logicamente tiene su codigo de cliente (por ejemplo un campo numerico). Lo
> que queremos es que al crear un nuevo cliente se busque el ultimo codigo de
> cliente, le sumamos 1 y añadimos el nuevo cliente.
>
> El problema viene cuando se trabaja en multiusuario. Tenemos que evitar que
> se creen 2 codigos de cliente iguales.
>
> Para ejemplificarlo, en lugar de poner nuestro codigo en C++, os pongo el
> siguiente 'pseudocodigo':
>
> use BASEDEDATOS
> set transaction isolation level serializable
> begin transaction
>
> // Punto 1: Obtenemos el ultimo registro
> select top(1) codigo from clientes order by codigo desc
> nuevocodigo = clientes.codigo+1
>
> // Punto 2: Grabamos
> insert into clientes (codigo) values(Nuevocodigo)
>
> commit
>
> En el pseudocodigo anterior, si 2 procesos se ejecutan simultaneamente,
> ambos ejecutan el Punto1 a la vez... los 2 procesos dan con el mismo codigo,
> duplicando el codigo de articulo.
>
> He probado con todos los niveles de aislamiento: READ COMMITTED, UNCOMMITED,
> SERIALIZABLE, REPEATABLE READS, SNAPSHOT, pero en todos falla.
>
> Supongo que esto debe hacerse mejor de otra forma (hacer el codigo como
> campo identity por ejemplo), pero no me sirve, ya que como os he comentado
> estamos migrando una aplicacion (programada al estilo XBase) y es una
> aplicacion bastante grande, lo tengo todo migrado a excepcion de este
> problema y no es solo al crear un cliente, sino en muhos otros puntos del
> programa.
>
> Gracias por adelantado.
>
> Saludos,
> Vicente Flich
> Flifeca Aplicaciones Informáticas
>
email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida