Como DB TRANSACTIONS realmente funcionam? Aprenda a controlar condições de corrida!

แชร์
ฝัง
  • เผยแพร่เมื่อ 29 ต.ค. 2024

ความคิดเห็น • 79

  • @WladsonCedraz
    @WladsonCedraz 7 หลายเดือนก่อน +27

    Video perfeito. Problema bem explicado, teorias de resolução bem explicados e código bem aplicado. Manda mais desse Pedrão, seria bem legal uma série de “problemas do cotidiano resolvidos” algo que trouxesse mais insights como esse.

  • @h4andr1x
    @h4andr1x 7 หลายเดือนก่อน +11

    Muito bom! Meses atrás eu também esbarrei nesse problema e descobri o mundo das race conditions kkkkk.
    Vou colocar aqui a resposta que fiz pra um comentário.
    Se não me engano, isso é apenas onde existe um conflito, uma condição de corrida. Por exemplo neste caso do estoque, se duas pessoas lerem o estoque como 1 e uma delas comprar primeiro, a segunda pessoa que for comprar e leu o estoque como 1 já está desatualizado e portanto iria comprar um produto achando que tem estoque quando na verdade não tem. Percebe o conflito? Isso é uma race condition. No caso, colocar um campo versao, o sistema pode verificar se a versão ainda é a mesma colocando no where do update, garantindo que a atualização do estoque só ocorra se a linha da tabela não foi alterada por outra pessoa.
    Eu fiz um resumo rápido aqui e provavelmente insuficiente pra uma visão clara do problema. Sugiro que você pesquise no google sobre race conditions em banco de dados e faça testes na prática para internalizar o conhecimento.

  • @diiegors90
    @diiegors90 7 หลายเดือนก่อน +17

    excelente como sempre. Um detalhe sobre optimistic lock, é que se tiver muito choque de atualização gerará muito rollback e em certos casos pode ficar mais caro.

    • @gstella
      @gstella 7 หลายเดือนก่อน +3

      e o que você faria nesse caso? é pro meu tcc 😅

    • @gabrielazevedo5232
      @gabrielazevedo5232 7 หลายเดือนก่อน

      Deixando uma ward aqui pra saber a resposta. Fiquei curioso

    • @heraldo623
      @heraldo623 7 หลายเดือนก่อน +2

      Provavelmente ele quis dizer em uma transação longa que envolve a atualização ou criação de objetos novos. O rollback tem que desfazer isso tudo caso o update no optimistic lock falhe.

    • @IsaacBatistapns
      @IsaacBatistapns 7 หลายเดือนก่อน +1

      ​@@gstella acho que aí vc teria que escolher entre:
      - o custo maior do optimistic
      - a performance pior do pessimistic

  • @vitaminaninja
    @vitaminaninja 7 หลายเดือนก่อน +7

    Opa pedro, uma correção, o for update ou o lock do serializable, só vai bloquear a leitura caso as outras transactions estiverem no mesmo nível de isolamento, caso uma estiver em outro como no read commited por exemplo, ele ainda consegue ler o registro selecionado com for update e etc, e no seu sistema vc tem alternativas para contornar isso caso possa atrapalhar a sua query como usar um skip locked aonde ele vai ignorar os registros bloqueados e realizar o select no restante. Outra sobre o serializable, ele nao necessariamente vai dar lock na tabela inteira, se vc dar um for update em apenas um registro da tabela, outras transactions com o nível de isolamento serializable, vão conseguir ler os outros registros em paralelo, então o serializable não é uma execução sequencial no literal, vc pode ter 2 transactions com o nivel serializable executando em paralelo desde que elas não alterem registros bloqueados pelas outras.

    • @vitaminaninja
      @vitaminaninja 7 หลายเดือนก่อน +2

      Lembrando que ao utilizar certos níveis de isolamento vc pode correr o risco de ter 2 transações em deadlock, algo que seria legal ser explicado no vídeo.

  • @thevocoder
    @thevocoder 7 หลายเดือนก่อน +8

    Nem acredito que esse video foi lançado, to nesse exato momento resolvendo um problema de race conditions na minha aplicação, usuários estão sendo duplicados no meu banco de dados

  • @Ddiidev
    @Ddiidev 7 หลายเดือนก่อน +3

    Perfeito macho, uma ideia bem simples que nunca tinha pensado nisso. Engraçado que as vezes o simples/óbvio precisa ser dito.

    • @carloshenrique-ov5nk
      @carloshenrique-ov5nk 7 หลายเดือนก่อน

      calma femea kkkk

    • @Ddiidev
      @Ddiidev 7 หลายเดือนก่อน +2

      @@carloshenrique-ov5nk ai dento 'kkkkk

  • @LeandroSantos-zd2jd
    @LeandroSantos-zd2jd 7 หลายเดือนก่อน

    caralho voce explico de maneira mais direta e eficaz que eu ja vi aqui no youtube parabens!

  • @AlissonPaulino777
    @AlissonPaulino777 7 หลายเดือนก่อน

    Você é demais, Pedro. Explicação clara, áudio e vídeo perfeitos e exemplo simples de entendimento. Desde quando comecei a te seguir, não perco 1 vídeo sequer. Aprendo muito contigo.

  • @SilasSWF
    @SilasSWF 6 หลายเดือนก่อน

    Excelente vídeo irmão, parabéns, vlw mesmo!!!!

  • @宗派
    @宗派 7 หลายเดือนก่อน

    Caraca, olha a qualidade desse áudio kkkkk tava assistindo um vídeo e cliquei nesse, DIFERENÇA ABSURDA!! Bom vídeo!

  • @dev_michael_404
    @dev_michael_404 7 หลายเดือนก่อน +2

    Tive que usar algumas estratégias para lidar com concorrência e condições de corrida na rinha de backend. O conteudo desse canal é fantastico.

    • @phenpessoa
      @phenpessoa  7 หลายเดือนก่อน +1

      Muito obrigado! :)

  • @adriel_borges
    @adriel_borges 7 หลายเดือนก่อน

    Conteúdo massa, pfv não pare.

  • @yuribarbosa8846
    @yuribarbosa8846 7 หลายเดือนก่อน +2

    Cara, seu conteúdo é excelente. Poderia assistir todos os dias um vídeo novo kkkkk.

  • @eli3150
    @eli3150 7 หลายเดือนก่อน

    Eu achei muito interessante essa solução. Só tenho algumas dúvidas, por exemplo; Será que a performance de fazer um retry caso a version seja diferente, não poderia ser a mesma de dar lock no registro?
    Se 100 registros ao mesmo tempo encontrar a version diferente no select de um mesmo registro, o retry de todas elas ao mesmo tempo não poderia ser menos performático que usar lock?
    São apenas questionamentos, mas talvez o custo do lock seja tão grande, que a tecnica do version seja bem melhor mesmo com retries

  • @begonegeek
    @begonegeek 7 หลายเดือนก่อน +1

    lembrei de quando desenvolvi o chat via socket, as vezes se a pessoa clica-se no mesmo tempo para aceitar o atendimento era uma briga de um puxando para o outro, 1 linha de conferencia resolveu 100% os problema mais ou menos como você fez com o version :3

  • @WelitonRibeiro
    @WelitonRibeiro 7 หลายเดือนก่อน

    E para um cenário onde a um insert no banco depois de um retorno de uma api, mas podem existir muitas chamadas para um mesmo registro (que terá esse insert da chamada na api) para essa api e acaba por duplicar essa chamada, já que era para acontecer só uma chamada por dia, visto que a resposta da api não é instantânea.

  • @catarinayikake4820
    @catarinayikake4820 7 หลายเดือนก่อน

    Skill de malandro essa de usar o version haha gostei muito!! video ótimo

  •  7 หลายเดือนก่อน

    Explicado de uma forma muito clara. Obrigado.

  • @danilosoares290
    @danilosoares290 7 หลายเดือนก่อน

    Simples e funcional! Parabéns!! Muito bem explicado.

  • @omonteirox
    @omonteirox 7 หลายเดือนก่อน

    Que didática, que oratória.
    Parabéns Pedro, continue fazendo vídeos frequentes, por favor.

  • @andrelsv2682
    @andrelsv2682 7 หลายเดือนก่อน +1

    Cara fantástico esse tema! Achei muito legal as soluções apresentadas, em especial a última, que achei extremamente simples porém fiquei pensando: isso não causaria uma grande quantidade de erros sempre que uma requisição tentasse atualizar e outra já tiver passado na frente, pensando em um elevado número de requisições simultâneas o estresse com erros (para o usuário) não seria o mesmo da perda de performasse?

    • @PauloGabriel-of6hm
      @PauloGabriel-of6hm 7 หลายเดือนก่อน

      Eu tava pensando nisso tbm, por exemplo a versão começa como 0 aí João e Marcelo clicaram pra comprar ao mesmo tempo e só tem mais duas unidades do produto, a requisição do João terminou primeiro portanto agora a versão está 1, quando Marcelo for atualizar para ele a versão ainda será 0 resultando na falha da compra quando na verdade ainda possui uma unidade

  • @Piikeda
    @Piikeda 7 หลายเดือนก่อน

    top!
    Parabens pelo conteudo!

  • @raimundoclessyo8943
    @raimundoclessyo8943 7 หลายเดือนก่อน

    Amei, já tive essa dúvida mas nunca fui atrás para sanar, obrigado por mostrar ❤.

  • @Mike-yu2wh
    @Mike-yu2wh 7 หลายเดือนก่อน

    Esse vídeo é incrível

  • @sandromiranda431
    @sandromiranda431 7 หลายเดือนก่อน

    Muito bom Pedro! ganhou um inscrito

    • @phenpessoa
      @phenpessoa  7 หลายเดือนก่อน

      Muito obrigado e seja bem vindo! :)

  • @OtavioHenriqueSO
    @OtavioHenriqueSO 7 หลายเดือนก่อน

    Muito interessante, acho que já sei onde posso usar isso.

  • @dedeh-lives
    @dedeh-lives 7 หลายเดือนก่อน

    Cara essa parte da versão, serveria bem para algo como:
    Eu tenho uma tabela que tem uma lista de números, e sempre que alguém reserva aquele numero, a lista e atualizada.
    E tem uma cron que também atualiza aquela lista, podendo colocar alguns números de novo dentro dela, como números que acabei de tirar no metodo acima.
    E elas podem rodar ao mesmo tempo sendo que a cron roda a cada 1 minuto e o metodo pode ser chamado por um usúario toda hora.

  • @Hugo.Digital
    @Hugo.Digital 7 หลายเดือนก่อน +2

    Acha que da pra resolver isso no padrão CQRS ? Se não, qual padrão de arquitetura poderia ser uma opção pra resolver ?
    Obs: Que tema sensacional.

    • @h4andr1x
      @h4andr1x 7 หลายเดือนก่อน +5

      Esse problema não exige um design de sistema específico para resolvê-lo. Você tem apenas duas opções: lock otimista ou lock pessimista. Você pode implementar com MVC, CQRS, etc.

  • @rafapcarvalho1
    @rafapcarvalho1 7 หลายเดือนก่อน

    É possível ver o título do conteúdo de membros para dar um gostinho e vontade de se tornar membro

  • @emersontecnologiadainforma1950
    @emersontecnologiadainforma1950 7 หลายเดือนก่อน

    Boa tarde!
    E se ao invés de tratar isso no Backend fazer uma função no BD que encapsule essa lógica e retorna a informação para o backened com o sucesso ou não.
    Nesse caso ainda precisaria de controle de transição?
    Também acredito que se colocar no update na cláusula where id = p_id and qtde_estoque >= p_qtde_pedido e tratar com um row affected pode solucionar.

  • @TiagoSouza-rk9cx
    @TiagoSouza-rk9cx 7 หลายเดือนก่อน

    Pedrao muito massa essa explicação 😮

  • @ViniciusRodrigues-yc3gf
    @ViniciusRodrigues-yc3gf 7 หลายเดือนก่อน

    O que você acha de orms? Usa eles em projetos em Go? Ou vai com o sql puro mesmo?

  • @ph7jack
    @ph7jack 7 หลายเดือนก่อน

    Muito didático 👏🏻👏🏻👏🏻

  • @sherlockgomes
    @sherlockgomes 7 หลายเดือนก่อน

    Mto bom!

  • @RichellyItalo
    @RichellyItalo 7 หลายเดือนก่อน

    Por favor que tema/color scheme é esse que você está utilizando no vim?

    • @phenpessoa
      @phenpessoa  7 หลายเดือนก่อน

      É o catppuccin

  • @baltha_zar
    @baltha_zar 7 หลายเดือนก่อน +1

    vesh n entendi, enquanto ter várias pessoas acessando o msm endpoint, eu tenho q dar sorte de n ter ninguém atualizando a versão pra conseguir executar a query? e no caso de criar registros em várias tabelas, todas tem q ter uma verificação de versão?

    • @h4andr1x
      @h4andr1x 7 หลายเดือนก่อน

      Se não me engano, isso é apenas onde existe um conflito, uma condição de corrida. Por exemplo, neste caso do estoque, se duas pessoas lerem o estoque como 1 e uma delas comprar primeiro, a segunda pessoa que for comprar e leu o estoque como 1 já está desatualizado e portanto iria comprar um produto achando que tem estoque quando na verdade não tem. Percebe o conflito? Isso é uma race condition. No caso, colocar um campo versao, o sistema pode verificar se a versão ainda é a mesma colocando no where do update, garantindo que a atualização do estoque só ocorra se a linha da tabela não foi alterada por outra pessoa.
      Eu fiz um resumo rápido aqui e provavelmente insuficiente pra uma visão clara do problema. Sugiro que você pesquise no google sobre race conditions em banco de dados e faça testes na prática para internalizar o conhecimento.

  • @gustavopoa
    @gustavopoa 7 หลายเดือนก่อน

    Excelente, parabéns!

  • @dev-muca
    @dev-muca 7 หลายเดือนก่อน

    Pedrão, achei muito interessante o assunto do vídeo, tentei replicar o código com NodeJS e MySQL, porém, no primeiro cenário não tive o problema dos -90, sabe me dizer se o Node ou o próprio MySQL já faz a tratativa do problema apresentado no vídeo? Obg, abraços..

    • @phenpessoa
      @phenpessoa  7 หลายเดือนก่อน

      Você está fazendo os requests concurrentemente ou sequencialmente? Se os requests forem sequenciais não terá problema.

  • @WaldirBorbaJunior
    @WaldirBorbaJunior 7 หลายเดือนก่อน

    Muito bom mesmo.

  • @alangraton2000
    @alangraton2000 7 หลายเดือนก่อน

    muito interessante, ótimo vid ^-^

  • @emersonfreire7782
    @emersonfreire7782 7 หลายเดือนก่อน

    Excelente

  • @DevMartins_
    @DevMartins_ 7 หลายเดือนก่อน

    Topp! Pedro se possível nos mostre como configurou o LSP do Glean no neovim! Ficaria agradecido se pudesse ajudar kkkkk 😃

    • @phenpessoa
      @phenpessoa  7 หลายเดือนก่อน +1

      Boa ideia!

  • @CGGamess
    @CGGamess 7 หลายเดือนก่อน

    colocar as compras em uma queue tambem seria uma boa pratica? tipo a amazon. voce faz a compra, porem ele demora um tempo ate chegar a confirmação

    • @heraldo623
      @heraldo623 7 หลายเดือนก่อน

      Filas são usadas pra controlar a carga máxima que o sistema pode receber. Não significa que todos os pedidos são processados sequencialmente.
      Eu posso definir um limite máximo de X pedidos em processamento e encaminhar o excesso para a fila.

  • @caiomarcatti12
    @caiomarcatti12 7 หลายเดือนก่อน

    O mysql tem essa condição?

  • @ViniciusRodrigues-yc3gf
    @ViniciusRodrigues-yc3gf 7 หลายเดือนก่อน

    Ótimo conteúdo

  • @pcreis
    @pcreis 7 หลายเดือนก่อน

    Muito bom..!! Parabéns ...

  • @betinhoabl1
    @betinhoabl1 7 หลายเดือนก่อน

    Bem interessante

  • @eduardohenriquelisboaalves3217
    @eduardohenriquelisboaalves3217 7 หลายเดือนก่อน

    ótimo vídeo

  • @lucas.vasconcelos
    @lucas.vasconcelos 7 หลายเดือนก่อน

    video excelente!

  • @caioalves8319
    @caioalves8319 7 หลายเดือนก่อน

    Qual o tema?

  • @junior.santana
    @junior.santana 7 หลายเดือนก่อน

    Não entendi muito bem a solução com versa pra esse cenário. Entendo que o problema seria alguém comprar um item sem ter mais em estoque pq durante o processo de compra o saldo foi alterado e chegou a zero.
    Só o fato de outro usuário ter feito a compra e ter atualizado o registro não me impede de fazer o mesmo.
    Nesse caso o update não deveria verificar "quantidade > 0"?

    • @phenpessoa
      @phenpessoa  7 หลายเดือนก่อน +1

      Sim! Mas na hora de fazer o update, a versão no banco vai estar diferente, o que significa que aquele registro foi alterado, e aí o update vai ser “cancelado”. Na verdade, o que acontece é que a WHERE clause retorna “No Rows”, então nenhum registro é atualizado. Mas em termos práticos entende-se que o update foi “cancelado”. Faz sentido?

    • @junior.santana
      @junior.santana 7 หลายเดือนก่อน

      @@phenpessoa então eu entendi o funcionamento, mas nesse cenário me parece q mesmo que outra request tenha alterado o registro, como o saldo ainda é maior que zero a segunda request poderia prosseguir com a operação sem problemas.
      Imagino que essa versão seria útil num cenário em que apenas uma requisição possa ter acesso a um recurso específico como a reserva de um assento em um vôo, pois se outra requisição concorrente já o reservou a segunda teria que falhar mesmo. Só que aí não sei como faria com update.
      (Eu sempre utilizei o "for update" mas nunca trabalhei com um sistema com uma carga alta que exigisse uma solução mais elaborada)

  • @AlmirBispo-CSV-Comp-DB
    @AlmirBispo-CSV-Comp-DB 7 หลายเดือนก่อน +1

    De qualquer maneira,o sistema com versão tem um problema.Se dois acessos recebem a mesma versão no momento da leitura eles terão concorrencia no momento da escrita.

    • @phenpessoa
      @phenpessoa  7 หลายเดือนก่อน +3

      Isso não acontece. O PostgreSQL garante que updates sempre vão precisar de um ROW EXCLUSIVE lock na hora de rodar, o que garante que não existe condição de corrida (a nível de banco) durante os writes. Pode acontecer a nível de aplicação (como eu mostrei no vídeo), mas não a nível de banco.
      Tanto que o no primeiro exemplo o resultado final sempre vai ser -90. Se existisse condição de corrida a nível de banco, esse número poderia variar toda vez que a gente escrevesse o código.

    • @rovannl
      @rovannl 7 หลายเดือนก่อน

      @@phenpessoa mas aí dá no mesmo que fazer o FOR UPDATE, a transação fica pendente até que a outra termine. De qualquer forma, não utilize update no saldo para fazer um controle de estoque. Faça um fluxo, se necessário uma fila.

  • @MarcosVMSoares
    @MarcosVMSoares 6 หลายเดือนก่อน

    Changeset ? Pq vc gostam de aprender as técnicas modernas de programação e nao entender o pq Phoenix ja vem com quase tudo pra solucionar esse velho problemas?

  • @mariojunior1726
    @mariojunior1726 7 หลายเดือนก่อน

    FOR UPDATE SKIP LOCKED resolve melhor ao meu ver

  • @AlmirBispo-CSV-Comp-DB
    @AlmirBispo-CSV-Comp-DB 7 หลายเดือนก่อน

    controle de concorrência

  • @josephklimber195
    @josephklimber195 7 หลายเดือนก่อน

    Top demais.