Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Race Conditions em Microsserviços: Desmistificando um Problema Comum em Arquiteturas Distribuídas

Race Conditions em Microsserviços: Desmistificando um Problema Comum em Arquiteturas Distribuídas

Os microsserviços são uma realidade na arquitetura de sistemas distribuídos, porém, o aumento da complexidade desses sistemas trouxe novos desafios, em especial na garantia da integridade e consistência dos dados de negócio. Com a crescente adoção de microsserviços, problemas de concorrência, como Race Conditions e Lost Update, se tornaram mais frequentes e podem comprometer a eficiência dos seus sistemas. Nesta talk, vamos explorar as causas que levam a problemas de Race Conditions em microsserviços, assim como heurísticas para identificar e controlar situações de concorrência.

Talk apresentada na trilha de Microsserviços II no TDC CONNECTIONS 2023.
Talk apresentada na Weekly II no TDC CONNECTIONS 2023.

Jordi Henrique Silva

March 24, 2023
Tweet

More Decks by Jordi Henrique Silva

Other Decks in Technology

Transcript

  1. Race Conditions em Microsserviços: Desmistificando um Problema
    Comum em Arquiteturas Distribuídas

    View full-size slide

  2. Era dos MAINFRAMEs

    View full-size slide

  3. Cliente Funcionaria
    Sistema Database

    View full-size slide

  4. solicita
    Cliente Funcionaria
    Sistema Database

    View full-size slide

  5. request
    Cliente Funcionaria
    Sistema Database
    solicita

    View full-size slide

  6. request
    response
    Cliente Funcionaria
    Sistema Database
    solicita

    View full-size slide

  7. request
    response
    Cliente Funcionaria
    Sistema Database
    responde
    solicita

    View full-size slide

  8. Era dos
    Microsserviços

    View full-size slide

  9. request
    response
    Cliente Funcionaria
    Sistema Database
    responde
    Solicita

    View full-size slide

  10. request
    response
    Sistema Database

    View full-size slide

  11. request
    response
    Sistema Database

    View full-size slide

  12. request
    response
    Sistema Database

    View full-size slide

  13. request
    response
    Sistema Database

    View full-size slide

  14. Como o aumento de
    acesso simultâneo
    afeta os
    negócios?

    View full-size slide

  15. Surface Web
    Deep Web
    Dark Web

    View full-size slide

  16. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  17. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  18. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  19. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  20. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  21. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  22. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  23. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  24. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  25. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  26. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  27. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  28. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  29. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  30. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  31. E se mais de um
    usuário tentar
    reservar a mesma
    poltrona
    simultaneamente?

    View full-size slide

  32. João Maria
    select p.*
    from poltrona p
    where id = 1

    View full-size slide

  33. João Maria
    select p.*
    from poltrona p
    where id = 1 select p.*
    from poltrona p
    where id = 1

    View full-size slide

  34. Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    João Maria
    select p.*
    from poltrona p
    where id = 1 select p.*
    from poltrona p
    where id = 1

    View full-size slide

  35. Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    João Maria
    select p.*
    from poltrona p
    where id = 1 select p.*
    from poltrona p
    where id = 1
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:

    View full-size slide

  36. Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    João Maria
    update poltrona
    set reservado = true,
    reservadoPara = ‘joao’
    where id = 1
    select p.*
    from poltrona p
    where id = 1 select p.*
    from poltrona p
    where id = 1
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:

    View full-size slide

  37. Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    João Maria
    update poltrona
    set reservado = true,
    reservadoPara = ‘joao’
    where id = 1
    select p.*
    from poltrona p
    where id = 1 select p.*
    from poltrona p
    where id = 1
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    update poltrona
    set reservado = true,
    reservadoPara = ‘maria’
    where id = 1

    View full-size slide

  38. 1 linha atualizada
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: true
    reservadoPara: joao
    João Maria
    update poltrona
    set reservado = true,
    reservadoPara = ‘joao’
    where id = 1
    select p.*
    from poltrona p
    where id = 1 select p.*
    from poltrona p
    where id = 1
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    update poltrona
    set reservado = true,
    reservadoPara = ‘maria’
    where id = 1

    View full-size slide

  39. 1 linha atualizada
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: true
    reservadoPara: joao
    João Maria
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: true
    reservadoPara: maria
    update poltrona
    set reservado = true,
    reservadoPara = ‘joao’
    where id = 1
    select p.*
    from poltrona p
    where id = 1 select p.*
    from poltrona p
    where id = 1
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    update poltrona
    set reservado = true,
    reservadoPara = ‘maria’
    where id = 1
    1 linha atualizada

    View full-size slide

  40. 1 linha atualizada
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: true
    reservadoPara: joao
    João Maria
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: true
    reservadoPara: maria
    update poltrona
    set reservado = true,
    reservadoPara = ‘joao’
    where id = 1
    select p.*
    from poltrona p
    where id = 1 select p.*
    from poltrona p
    where id = 1
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    update poltrona
    set reservado = true,
    reservadoPara = ‘maria’
    where id = 1
    1 linha atualizada

    View full-size slide

  41. Race Conditions

    View full-size slide

  42. Race Conditions em Microsserviços: Desmistificando um Problema
    Comum em Arquiteturas Distribuídas

    View full-size slide

  43. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    //read
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    //process
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    //write
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  44. Solução Ingênua

    View full-size slide

  45. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    //read
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    //process
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    //write
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  46. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    //read
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    //process
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    //write
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  47. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    //read
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    //process
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    //write
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  48. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    //read
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    //process
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    //write
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  49. read process

    View full-size slide

  50. read process

    View full-size slide

  51. read process write
    ANTI-PATTERN

    View full-size slide

  52. Syncronized?

    View full-size slide

  53. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Syncronized
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  54. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Syncronized
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  55. Thread 1 Thread 2

    View full-size slide

  56. POST /poltronas/1/reservas
    Thread 1 Thread 2

    View full-size slide

  57. POST /poltronas/1/reservas
    Thread 1 Thread 2

    View full-size slide

  58. POST /poltronas/1/reservas
    Thread 1 Thread 2
    POST /poltronas/1/reservas

    View full-size slide

  59. POST /poltronas/1/reservas
    Thread 1 Thread 2
    POST /poltronas/1/reservas

    View full-size slide

  60. POST /poltronas/1/reservas
    HTTP 200
    Thread 1 Thread 2
    POST /poltronas/1/reservas

    View full-size slide

  61. POST /poltronas/1/reservas
    HTTP 200
    Thread 1 Thread 2
    POST /poltronas/1/reservas

    View full-size slide

  62. POST /poltronas/1/reservas
    HTTP 200
    HTTP 422, “Poltrona indisponível”
    Thread 1 Thread 2
    POST /poltronas/1/reservas

    View full-size slide

  63. Lock Distribuído?

    View full-size slide

  64. Você ou seu time
    domina essa tecnologia?

    View full-size slide

  65. Já possui alguma
    destas tecnologias na
    sua infraestrutura?

    View full-size slide

  66. Pessimistic Locking

    View full-size slide

  67. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Syncronized
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    //RESTANTE DO CODIGO OMITIDO
    }
    }

    View full-size slide

  68. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Syncronized
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id, PESSIMISTIC_WRITE)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    //RESTANTE DO CODIGO OMITIDO
    }
    }

    View full-size slide

  69. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Syncronized
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id, PESSIMISTIC_WRITE)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    //RESTANTE DO CODIGO OMITIDO
    }
    }

    View full-size slide

  70. select p.*
    from poltrona p
    where p.id = :poltronaId
    for update

    View full-size slide

  71. select p.*
    from poltrona p
    where p.id = :poltronaId
    for update

    View full-size slide

  72. João Maria
    select p.*
    from poltrona p
    where id = 1
    for update

    View full-size slide

  73. João Maria
    select p.*
    from poltrona p
    where id = 1
    for update
    select p.*
    from poltrona p
    where id = 1
    for update

    View full-size slide

  74. Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    João Maria
    select p.*
    from poltrona p
    where id = 1
    for update
    select p.*
    from poltrona p
    where id = 1
    for update

    View full-size slide

  75. Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    João Maria
    select p.*
    from poltrona p
    where id = 1
    for update
    select p.*
    from poltrona p
    where id = 1
    for update

    View full-size slide

  76. Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    João Maria
    select p.*
    from poltrona p
    where id = 1
    for update
    select p.*
    from poltrona p
    where id = 1
    for update

    View full-size slide

  77. Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    João Maria
    update poltrona
    set reservado = true,
    reservadoPara = ‘joao’
    where id = 1
    select p.*
    from poltrona p
    where id = 1
    for update
    select p.*
    from poltrona p
    where id = 1
    for update

    View full-size slide

  78. Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    João Maria
    COMMIT
    update poltrona
    set reservado = true,
    reservadoPara = ‘joao’
    where id = 1
    select p.*
    from poltrona p
    where id = 1
    for update
    select p.*
    from poltrona p
    where id = 1
    for update

    View full-size slide

  79. 1 linha atualizada
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: true
    reservadoPara: joao
    João Maria
    COMMIT
    update poltrona
    set reservado = true,
    reservadoPara = ‘joao’
    where id = 1
    select p.*
    from poltrona p
    where id = 1
    for update
    select p.*
    from poltrona p
    where id = 1
    for update

    View full-size slide

  80. 1 linha atualizada
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: true
    reservadoPara: joao
    João Maria
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: true
    reservadoPara: joao
    COMMIT
    update poltrona
    set reservado = true,
    reservadoPara = ‘joao’
    where id = 1
    select p.*
    from poltrona p
    where id = 1
    for update
    select p.*
    from poltrona p
    where id = 1
    for update

    View full-size slide

  81. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Syncronized
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id, PESSIMISTIC_WRITE)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  82. Se houver alto volume
    de requisições causando
    alta espera por acesso
    da linha?

    View full-size slide

  83. É possível diminuir o
    tempo do lock?

    View full-size slide

  84. ... Trocarmos a
    estratégia de evitar
    conflitos para detectar
    conflitos?

    View full-size slide

  85. Optimistic Locking

    View full-size slide

  86. @Entity
    class Poltrona(
    @field:Column(nullable = false) val descricao: String,
    @field:Column(nullable = false) var reservadoPara: String,
    @field:Column(nullable = false) var reservado: Boolean = false
    @field:Version var version: Long
    ) {
    @Id
    @GeneratedValue
    var id: Long? = null;
    }

    View full-size slide

  87. @Entity
    class Poltrona(
    @field:Column(nullable = false) val descricao: String,
    @field:Column(nullable = false) var reservadoPara: String,
    @field:Column(nullable = false) var reservado: Boolean = false,
    var version: Long
    ) {
    @Id
    @GeneratedValue
    var id: Long? = null;
    }

    View full-size slide

  88. @Entity
    class Poltrona(
    @field:Column(nullable = false) val descricao: String,
    @field:Column(nullable = false) var reservadoPara: String,
    @field:Column(nullable = false) var reservado: Boolean = false,
    @field:Version var version: Long
    ) {
    @Id
    @GeneratedValue
    var id: Long? = null;
    }

    View full-size slide

  89. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Syncronized
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id, PESSIMISTIC_WRITE)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  90. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Syncronized
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  91. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Syncronized
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    manager.merge(poltrona);
    return ok();
    }
    }

    View full-size slide

  92. update poltrona
    set reservado = true,
    reservadoPara = :user
    where id = :poltronaId

    View full-size slide

  93. update poltrona
    set version = 1,
    reservado = true,
    reservadoPara = :user
    where id = :poltronaId
    and version = 0

    View full-size slide

  94. João Maria
    select p.*
    from poltrona p
    where id = 1

    View full-size slide

  95. João Maria
    select p.*
    from poltrona p
    where id = 1
    select p.*
    from poltrona p
    where id = 1

    View full-size slide

  96. Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    version: 0
    João Maria
    select p.*
    from poltrona p
    where id = 1
    select p.*
    from poltrona p
    where id = 1

    View full-size slide

  97. Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    version: 0
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    version: 0
    João Maria
    select p.*
    from poltrona p
    where id = 1
    select p.*
    from poltrona p
    where id = 1

    View full-size slide

  98. Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    version: 0
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    version: 0
    João Maria
    select p.*
    from poltrona p
    where id = 1
    select p.*
    from poltrona p
    where id = 1

    View full-size slide

  99. Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    version: 0
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    version: 0
    update poltrona
    set version = 1,
    reservado = true,
    reservadoPara = ‘joao’
    where id = 1
    and version = 0
    João Maria
    select p.*
    from poltrona p
    where id = 1
    select p.*
    from poltrona p
    where id = 1

    View full-size slide

  100. 1 linha atualizada
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    version: 0
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    version: 0
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: true
    reservadoPara: joao
    version: 1
    update poltrona
    set version = 1,
    reservado = true,
    reservadoPara = ‘joao’
    where id = 1
    and version = 0
    João Maria
    select p.*
    from poltrona p
    where id = 1
    select p.*
    from poltrona p
    where id = 1

    View full-size slide

  101. 1 linha atualizada
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    version: 0
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    version: 0
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: true
    reservadoPara: joao
    version: 1
    update poltrona
    set version = 1,
    reservado = true,
    reservadoPara = ‘joao’
    where id = 1
    and version = 0
    João Maria
    select p.*
    from poltrona p
    where id = 1
    select p.*
    from poltrona p
    where id = 1

    View full-size slide

  102. 1 linha atualizada
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    version: 0
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    version: 0
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: true
    reservadoPara: joao
    version: 1
    update poltrona
    set version = 1,
    reservado = true,
    reservadoPara = ‘maria’
    where id = 1
    and version = 0
    update poltrona
    set version = 1,
    reservado = true,
    reservadoPara = ‘joao’
    where id = 1
    and version = 0
    João Maria
    select p.*
    from poltrona p
    where id = 1
    select p.*
    from poltrona p
    where id = 1

    View full-size slide

  103. 1 linha atualizada
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    version: 0
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    version: 0
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: true
    reservadoPara: joao
    version: 1
    update poltrona
    set version = 1,
    reservado = true,
    reservadoPara = ‘maria’
    where id = 1
    and version = 0
    update poltrona
    set version = 1,
    reservado = true,
    reservadoPara = ‘joao’
    where id = 1
    and version = 0
    João Maria
    select p.*
    from poltrona p
    where id = 1
    select p.*
    from poltrona p
    where id = 1

    View full-size slide

  104. 1 linha atualizada
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    version: 0
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    version: 0
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: true
    reservadoPara: joao
    version: 1
    update poltrona
    set version = 1,
    reservado = true,
    reservadoPara = ‘maria’
    where id = 1
    and version = 0
    update poltrona
    set version = 1,
    reservado = true,
    reservadoPara = ‘joao’
    where id = 1
    and version = 0
    João Maria
    OptimisticLockException
    select p.*
    from poltrona p
    where id = 1
    select p.*
    from poltrona p
    where id = 1

    View full-size slide

  105. Como não estourar um erro na cara do usuário?!
    OptimisticLockException

    View full-size slide

  106. João
    POST /poltronas/1/reservas

    View full-size slide

  107. João
    POST /poltronas/1/reservas select p.*
    from poltrona p
    where id = 1

    View full-size slide

  108. João
    POST /poltronas/1/reservas select p.*
    from poltrona p
    where id = 1
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    version: 0

    View full-size slide

  109. João
    POST /poltronas/1/reservas select p.*
    from poltrona p
    where id = 1
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    version: 0
    update poltrona
    set version = 1,
    reservado = true,
    reservadoPara = ‘maria’
    where id = 1
    and version = 0

    View full-size slide

  110. João
    POST /poltronas/1/reservas select p.*
    from poltrona p
    where id = 1
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    version: 0
    update poltrona
    set version = 1,
    reservado = true,
    reservadoPara = ‘maria’
    where id = 1
    and version = 0
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: true
    reservadoPara: maria
    version: 1

    View full-size slide

  111. João
    POST /poltronas/1/reservas select p.*
    from poltrona p
    where id = 1
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    version: 0
    update poltrona
    set version = 1,
    reservado = true,
    reservadoPara = ‘maria’
    where id = 1
    and version = 0
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: true
    reservadoPara: maria
    version: 1
    update poltrona
    set version = 1,
    reservado = true,
    reservadoPara = ‘joao’
    where id = 1
    and version = 0

    View full-size slide

  112. João
    POST /poltronas/1/reservas select p.*
    from poltrona p
    where id = 1
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    version: 0
    update poltrona
    set version = 1,
    reservado = true,
    reservadoPara = ‘maria’
    where id = 1
    and version = 0
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: true
    reservadoPara: maria
    version: 1
    update poltrona
    set version = 1,
    reservado = true,
    reservadoPara = ‘joao’
    where id = 1
    and version = 0
    OptimisticLockException

    View full-size slide

  113. João
    POST /poltronas/1/reservas select p.*
    from poltrona p
    where id = 1
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: false
    reservadoPara:
    version: 0
    update poltrona
    set version = 1,
    reservado = true,
    reservadoPara = ‘maria’
    where id = 1
    and version = 0
    Poltrona
    --------------
    id: 1,
    descriçao: A3
    reservado: true
    reservadoPara: maria
    version: 1
    update poltrona
    set version = 1,
    reservado = true,
    reservadoPara = ‘joao’
    where id = 1
    and version = 0
    OptimisticLockException
    HTTP 500

    View full-size slide

  114. HTTP 500
    É uma mensagem
    muito genérica

    View full-size slide

  115. HTTP 409 CONFLICT

    View full-size slide

  116. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    try {
    manager.merge(poltrona);
    }catch (ex: OptimisticLockException){
    throw HttpStatusException(CONFLICT,"Impossivel realizar a reserva, tente novamente.")
    }
    return ok();
    }
    }

    View full-size slide

  117. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    try {
    manager.merge(poltrona);
    }catch (ex: OptimisticLockException){
    throw HttpStatusException(CONFLICT,"Impossivel realizar a reserva, tente novamente.")
    }
    return ok();
    }
    }

    View full-size slide

  118. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    try {
    manager.merge(poltrona);
    }catch (ex: OptimisticLockException){
    throw HttpStatusException(CONFLICT,"Impossivel realizar a reserva, tente novamente.")
    }
    return ok();
    }
    }

    View full-size slide

  119. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    try {
    manager.merge(poltrona);
    }catch (ex: OptimisticLockException){
    throw HttpStatusException(CONFLICT,"Impossivel realizar a reserva, tente novamente.")
    }
    return ok();
    }
    }

    View full-size slide

  120. Existe uma forma mais
    elegante...

    View full-size slide

  121. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {
    val poltrona = manager.find(Poltrona::class.java, id)
    ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.")
    if (poltrona.isReservada()) {
    throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel")
    }
    poltrona.reservadoPara = usuario;
    poltrona.reservado = true;
    try {
    manager.merge(poltrona);
    }catch (ex: OptimisticLockException){
    throw HttpStatusException(CONFLICT,"Impossivel realizar a reserva, tente novamente.")
    }
    return ok();
    }
    }

    View full-size slide

  122. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {...}
    @Error
    fun errorHandler(request: HttpRequest<*>, ex: OptimisticLockException): HttpResponse<*> {
    return HttpResponse.status(CONFLICT, ex.message)
    }
    }

    View full-size slide

  123. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {...}
    @Error
    fun errorHandler(request: HttpRequest<*>, ex: OptimisticLockException): HttpResponse<*> {
    return HttpResponse.status(CONFLICT,"Impossivel realizar a reserva, tente novamente.")
    }
    }

    View full-size slide

  124. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {...}
    @Error
    fun errorHandler(request: HttpRequest<*>, ex: OptimisticLockException): HttpResponse<*> {
    return HttpResponse.status(CONFLICT,"Impossivel realizar a reserva, tente novamente.")
    }
    }

    View full-size slide

  125. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {...}
    @Error
    fun errorHandler(request: HttpRequest<*>, ex: OptimisticLockException): HttpResponse<*> {
    return HttpResponse.status(CONFLICT,"Impossivel realizar a reserva, tente novamente.")
    }
    }

    View full-size slide

  126. @Controller("/api/v1/poltronas/{id}/reservas")
    class ReservaPoltronaController(val manager: EntityManager) {
    @Transactional
    @Post
    fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {...}
    @Error
    fun errorHandler(request: HttpRequest<*>, ex: OptimisticLockException): HttpResponse<*> {
    return HttpResponse.status(CONFLICT,"Impossivel realizar a reserva, tente novamente.")
    }
    }

    View full-size slide

  127. read process

    View full-size slide

  128. read process write
    ANTI-PATTERN

    View full-size slide

  129. Race Conditions
    LOST UPDATE

    View full-size slide

  130. @Syncronized

    View full-size slide

  131. Pessimistic Locking

    View full-size slide

  132. Pessimistic Locking
    Estratégia: Evitar Conflitos
    Quando utilizar: alto índice de conflitos, ambientes
    altamente concorrentes
    Vantagem: Aumento da consistência
    Desvantagem: Pode gerar alto nível de contenção
    levando a queda de produtividade das transações

    View full-size slide

  133. Pessimistic Locking
    Estratégia: Evitar Conflitos
    Quando utilizar: alto índice de conflitos, ambientes
    altamente concorrentes
    Vantagem: Aumento da consistência
    Desvantagem: Pode gerar alto nível de contenção
    levando a queda de produtividade das transações

    View full-size slide

  134. Pessimistic Locking
    Estratégia: Evitar Conflitos
    Quando utilizar: alto índice de conflitos, ambientes
    altamente concorrentes
    Vantagem: Aumento da consistência
    Desvantagem: Pode gerar alto nível de contenção
    levando a queda de produtividade das transações

    View full-size slide

  135. Pessimistic Locking
    Estratégia: Evitar Conflitos
    Quando utilizar: alto índice de conflitos, ambientes
    altamente concorrentes
    Vantagem: Não exige mudanças no codigo
    Desvantagem: Pode gerar alto nível de contenção
    levando a queda de produtividade das transações

    View full-size slide

  136. Optimistic Locking

    View full-size slide

  137. Optimistic Locking
    Estratégia: Detectar Conflitos
    Quando utilizar: baixo índice de conflitos, ambientes
    razoavelmente concorrentes
    Vantagem: Menor tempo de bloqueio, menor
    contenção de transações
    Desvantagem: em ambientes concorrentes pode gerar
    alto custo computacional, dado ao grande numero de
    rollbacks em transações

    View full-size slide

  138. Optimistic Locking
    Estratégia: Detectar Conflitos
    Quando utilizar: baixo índice de conflitos, ambientes
    razoavelmente concorrentes
    Vantagem: Menor tempo de bloqueio, menor
    contenção de transações
    Desvantagem: em ambientes concorrentes pode gerar
    alto custo computacional, dado ao grande numero de
    rollbacks em transações

    View full-size slide

  139. Optimistic Locking
    Estratégia: Detectar Conflitos
    Quando utilizar: baixo índice de conflitos, ambientes
    razoavelmente concorrentes
    Vantagem: Menor tempo de bloqueio, menor
    contenção de transações
    Desvantagem: em ambientes concorrentes pode
    gerar alto custo computacional, dado ao grande
    numero de rollbacks em transações

    View full-size slide

  140. Optimistic Locking
    Estratégia: Detectar Conflitos
    Quando utilizar: baixo índice de conflitos, ambientes
    razoavelmente concorrentes
    Vantagem: Menor tempo de bloqueio, menor
    contenção de transações
    Desvantagem: em ambientes concorrentes pode gerar
    alto custo computacional, dado ao grande numero de
    rollbacks em transações

    View full-size slide

  141. Outras estratégias que os
    Bancos de dados oferecem
    para lidar com problemas
    de concorrência

    View full-size slide

  142. Check Constraints
    Advisory Locks
    Table Locks
    Isolation Level

    View full-size slide

  143. Check Constraints
    Advisory Locks
    Table Locks
    Isolation Level

    View full-size slide

  144. Check Constraints
    Advisory Locks
    Table Locks
    Isolation Level

    View full-size slide

  145. Check Constraints
    Advisory Locks
    Table Locks
    Isolation Level

    View full-size slide

  146. Se você usa o Banco de dados ...
    ... apenas como repositório.
    VOCÊ ESTA SUB-UTILIZANDO!

    View full-size slide

  147. OBRIGADO!
    @JORDIHOFC

    View full-size slide