Skip to content

ensure upserts occur in READ_COMMITTED isolation level #17

@uladkasach

Description

@uladkasach

REPEATABLE_READ is not required for insert-only upserts (since we only check existence and insert rows for static entities, and only update the "current_version_pointer" table for dynamic entities - but that should not be a problem either).


Why do we want to do this? because otherwise REPEATABLE_READ results in deadlocks in high concurrency usage:

------------------------
LATEST DETECTED DEADLOCK
------------------------
2020-01-19 14:28:28 0x7fdb08c5b700
*** (1) TRANSACTION:
TRANSACTION 1886, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 10, OS thread handle 140578722281216, query id 205 172.19.0.1 svc_idea_curate update
INSERT INTO tag
LOCK WAIT 3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 10, OS thread handle 140578722281216, query id 205 172.19.0.1 svc_idea_curate update
INSERT INTO tag
      (uuid, name)
      VALUES
      (uuid(),  NAME_CONST('in_name',_utf8mb4'outdoors' COLLATE 'utf8mb4_unicode_ci'))
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 32 page no 4 n bits 72 index tag_ux1 of table `ideacurationdb`.`tag` trx id 1886 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 5; hex 7269766572; asc river;;
 1: len 8; hex 8000000000000002; asc         ;;

*** (2) TRANSACTION:
TRANSACTION 1887, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 9, OS thread handle 140578721740544, query id 207 172.19.0.1 svc_idea_curate update
INSERT INTO tag
      (uuid, name)
      VALUES
      (uuid(),  NAME_CONST('in_name',_utf8mb4'park' COLLATE 'utf8mb4_unicode_ci'))
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 32 page no 4 n bits 72 index tag_ux1 of table `ideacurationdb`.`tag` trx id 1887 lock_mode X locks gap before rec
Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 5; hex 7269766572; asc river;;
 1: len 8; hex 8000000000000002; asc         ;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 32 page no 4 n bits 72 index tag_ux1 of table `ideacurationdb`.`tag` trx id 1887 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 5; hex 7269766572; asc river;;
 1: len 8; hex 8000000000000002; asc         ;;

*** WE ROLL BACK TRANSACTION (2)

We were upserting two static entities, and they locked eachother because, it looks like, they were using a "gap" lock and affected the same gap. See https://dba.stackexchange.com/questions/202455/mysql-gap-lock-deadlock-on-inserts for more details

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions