$30 off During Our Annual Pro Sale. View Details »

Zup Tech Hour - Race Conditions em Microsserviços: um problema comum em arquiteturas distribuidas

Jordi Henrique Silva
April 14, 2023
38

Zup Tech Hour - Race Conditions em Microsserviços: um problema comum em arquiteturas distribuidas

Talk apresentada no Zup Tech Hours no dia 13 de abril de 2023. Discutimos o que é Race Conditions, e heurística para la identifica e exploramos 3 soluções, sendo elas @Syncronized da JVM, Pessimistic Locking e Optimistic Locking.

Ficou interessado?
Assista nesse endereço: https://www.youtube.com/live/80I5zv1sDHo?feature=share

Jordi Henrique Silva

April 14, 2023
Tweet

Transcript

  1. View Slide

  2. Era dos MAINFRAMEs

    View Slide

  3. Cliente Funcionaria
    Sistema Database

    View Slide

  4. solicita
    Cliente Funcionaria
    Sistema Database

    View Slide

  5. request
    Cliente Funcionaria
    Sistema Database
    solicita

    View Slide

  6. request
    response
    Cliente Funcionaria
    Sistema Database
    solicita

    View Slide

  7. request
    response
    Cliente Funcionaria
    Sistema Database
    responde
    solicita

    View Slide

  8. Era dos
    Microsserviços

    View Slide

  9. request
    response
    Cliente Funcionaria
    Sistema Database
    responde
    Solicita

    View Slide

  10. request
    response
    Sistema Database

    View Slide

  11. request
    response
    Sistema Database

    View Slide

  12. request
    response
    Sistema Database

    View Slide

  13. request
    response
    Sistema Database

    View Slide

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

    View Slide

  15. View Slide

  16. View Slide

  17. Surface Web
    Deep Web
    Dark Web

    View Slide

  18. View Slide

  19. View Slide

  20. View Slide

  21. Fundamentos

    View Slide

  22. View Slide

  23. View 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 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 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 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 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 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 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 Slide

  31. @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 Slide

  32. @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 Slide

  33. @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 Slide

  34. @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 Slide

  35. @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 Slide

  36. @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 Slide

  37. @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 Slide

  38. @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 Slide

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

    View Slide

  40. View Slide

  41. João

    View Slide

  42. João Maria

    View Slide

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

    View Slide

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

    View Slide

  45. 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 Slide

  46. 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 Slide

  47. 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 Slide

  48. 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 Slide

  49. 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 Slide

  50. 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 Slide

  51. 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 Slide

  52. Race Conditions

    View Slide

  53. View Slide

  54. View Slide

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

    View Slide

  56. @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 Slide

  57. Solução Ingênua

    View Slide

  58. @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 Slide

  59. @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 Slide

  60. @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 Slide

  61. @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 Slide

  62. read

    View Slide

  63. read

    View Slide

  64. read process

    View Slide

  65. read process

    View Slide

  66. read process write
    ANTI-PATTERN

    View Slide

  67. Soluções

    View Slide

  68. View Slide

  69. Syncronized?

    View Slide

  70. @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 Slide

  71. @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 Slide

  72. View Slide

  73. Thread 1

    View Slide

  74. Thread 1 Thread 2

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  82. View Slide

  83. View Slide

  84. View Slide

  85. View Slide

  86. Lock Distribuído?

    View Slide

  87. View Slide

  88. Você ou seu time
    domina essa tecnologia?

    View Slide

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

    View Slide

  90. View Slide

  91. View Slide

  92. View Slide

  93. View Slide

  94. View Slide

  95. Pessimistic Locking

    View Slide

  96. @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 Slide

  97. @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 Slide

  98. @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 Slide

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

    View Slide

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

    View Slide

  101. View Slide

  102. João

    View Slide

  103. João Maria

    View Slide

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

    View Slide

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

    View Slide

  106. 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 Slide

  107. 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 Slide

  108. 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 Slide

  109. 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 Slide

  110. 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 Slide

  111. 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 Slide

  112. 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 Slide

  113. @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 Slide

  114. View Slide

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

    View Slide

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

    View Slide

  117. E Se ...

    View Slide

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

    View Slide

  119. Optimistic Locking

    View Slide

  120. @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 Slide

  121. @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 Slide

  122. @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 Slide

  123. @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 Slide

  124. @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 Slide

  125. @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 Slide

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

    View Slide

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

    View Slide

  128. View Slide

  129. João

    View Slide

  130. João Maria

    View Slide

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

    View Slide

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

    View Slide

  133. 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 Slide

  134. 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 Slide

  135. 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 Slide

  136. 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 Slide

  137. 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 Slide

  138. 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 Slide

  139. 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 Slide

  140. 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 Slide

  141. 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 Slide

  142. View Slide

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

    View Slide

  144. View Slide

  145. João

    View Slide

  146. João

    View Slide

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

    View Slide

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

    View Slide

  149. 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 Slide

  150. 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 Slide

  151. 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 Slide

  152. 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 Slide

  153. 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 Slide

  154. 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 Slide

  155. HTTP 500
    É uma mensagem
    muito genérica

    View Slide

  156. HTTP 409 CONFLICT

    View Slide

  157. @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 Slide

  158. @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 Slide

  159. @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 Slide

  160. @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 Slide

  161. Existe uma forma mais
    elegante...

    View Slide

  162. @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 Slide

  163. @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 Slide

  164. @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 Slide

  165. @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 Slide

  166. @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 Slide

  167. @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 Slide

  168. View Slide

  169. CONCLUSÃO

    View Slide

  170. read

    View Slide

  171. read process

    View Slide

  172. read process write
    ANTI-PATTERN

    View Slide

  173. Race Conditions
    LOST UPDATE

    View Slide

  174. @Syncronized

    View Slide

  175. Pessimistic Locking

    View Slide

  176. 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 Slide

  177. 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 Slide

  178. 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 Slide

  179. 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 Slide

  180. Optimistic Locking

    View Slide

  181. 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 Slide

  182. 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 Slide

  183. 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 Slide

  184. 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 Slide

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

    View Slide

  186. Check Constraints
    Advisory Locks
    Table Locks
    Isolation Level

    View Slide

  187. Check Constraints
    Advisory Locks
    Table Locks
    Isolation Level

    View Slide

  188. Check Constraints
    Advisory Locks
    Table Locks
    Isolation Level

    View Slide

  189. Check Constraints
    Advisory Locks
    Table Locks
    Isolation Level

    View Slide

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

    View Slide

  191. OBRIGADO!
    @JORDIHOFC

    View Slide