Fórum Manipular Registros no BD #443844
23/05/2013
0
tenho uma tabela.. exemplo produtos, com 3 registros.. produto 1 2 e 3
meu banco esta em um servidor e tenho 3 pessoas acessando ao mesmo tempo
supondo que duas delas selecionem o produto 2 ao mesmo tempo para alteração..
a pessoa que salvar primeiro vai perder os dados alterados quando a segunda pessoa alterar!
fiz o seguinte, criei um flag na tabela produtos, caso uma pessoa acesse atribuo verdadeiro ao flag, e não deixo outra pessoa acessar o mesmo registro... essa é a melhor maneira de resolver o problema?? existe outra??
André Macedo
Curtir tópico
+ 0Posts
27/05/2013
Thiago Santana
Reservada são os pedidos do cliente. Daí meu estoque sempre vai ser qtd total - reservada.
Existem diversas formas! Costumo fazer dessa forma e me atende perfeitamente
Gostei + 0
27/05/2013
Guilherme Wiethaus
Não é a melhor maneira não. Pois se falhar na sua escrita ficará com um flag na tabela impedindo até mesmoq ue o proprio que escreveu acesse já que irá validar pelo flag que você impôs na sua regra de negócio.
O ideal é fazer através de transações, numa rede boa, a escrita é feita de forma rápida sem grandes atrasos e o bloqueio ao registro é muito rápido. Lembre que existem várias modalidades de bloqueios o que recomendo é o tipo Batch Optimistic que o bloqueio acontece no momento do post apenas e não no insert/edit. Com isto vale quem salvou por último o registro. Em rede ou sistema multi usuário isto é uma boa regra. Outra maneira é enviar um sinal de fumaça avisando o outro lado que você esta alterando o registro e ele não pode mexer nele...rsrs.. Brincadeirinha.
Uma outra forma em algumas regras de bancos é utilizar StoredProc, que também ao se entrar com um usuário fica esperando terminar para que libere aos outros executarem o mesmo procedimento armazenado.
Pode fazer um teste legal.
Faça uma trigger de inclusão, dentro dela um loop que realiza um loop de 10 segundos e um flag de entradas (grava em uma tabela) da trigger, fazendo uma condicional se ela estiver setada retorna exceção. Em uma janela T-SQL inclua um registro...vai ficar em loop por um tempo..tudo bem..deixa assim...
na outra janela, rapidamente inclua registro também....não deve retornar exceção ainda, e ficará esperando uma transação terminar...quando terminar a segunda janela que mandou o comando vai gerar a exceção no Trigger (gatilho). Isto é um troque para você entender o que esta acontecendo. Eu fiz um script ai embaixo, que eu proprio testei e explana exatamente o que te expliquei.
Abaixo código para criar as tabelas necessárias para o teste:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[A](
[Valor] [int] NULL
) ON [PRIMARY]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[B](
[Flag] [int] NULL
) ON [PRIMARY]
GO
INSERT [dbo].[B] ([Flag]) VALUES (0)
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [dbo].[TESTE_A]
ON [dbo].[A]
AFTER INSERT
AS
BEGIN
BEGIN TRY
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @X INT;
-- Insert statements for trigger here
IF EXISTS (SELECT * FROM B WHERE Flag = 1)
BEGIN
RAISERROR ('Erro 001: Esta setado o Flag.', 16, 1);
RETURN;
END;
UPDATE B SET Flag = 1 FROM B;
--SET @x = 0;
SELECT GETDATE();
WAITFOR DELAY '00:00:10.000'; -- Espera por 10 segundos
SELECT GETDATE();
--SET @x = @x + 1;
END TRY
BEGIN CATCH
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
SELECT @ErrorMessage = ERROR_MESSAGE();
SELECT @ErrorSeverity = ERROR_SEVERITY();
SELECT @ErrorState = ERROR_STATE();
ROLLBACK TRAN;
RAISERROR ( @ErrorMessage, -- Message text.
@ErrorSeverity, -- Severity.
@ErrorState -- State.
);
PRINT 'ERROR_MESSAGE: ' + @ErrorMessage + ' ERROR_SEVERITY ' + CAST(@ErrorSeverity AS VARCHAR(50)) + ' ERROR_STATE: ' + @ErrorState;
RETURN;
END CATCH
END
GO
Numa janela coloque o seguinte:
UPDATE B SET Flag = 0 FROM B; INSERT INTO A (Valor) VALUES (1);
Na outra janela coloque:
INSERT INTO A (Valor) VALUES (2);
Troque rapidamente entre uma janela e outra e para executar o código no SQL Server 2008 pressione F5.
Verificará que um fica executando 10 segundos enquanto o outro ainda não entrou no trigger (gatilho) até que o primeiro termine. Este é um exemplo típico de bloqueio para evitar que um execute enquanto outro está terminando um processo todo.
Abraços
Gostei + 0
27/05/2013
Guilherme Wiethaus
Abraços
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)