Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Por que o bloqueio de predicado explícito do MySQL não permite instruções INSERT fora do bloqueio de predicado


O SELECT FOR UPDATE está bloqueando entre 1 e o próximo valor na tabela de funcionários. Como não há próximo valor, ele está bloqueando até o supremum pseudo-record . Isso pode ser visto em information_schema.innodb_locks :
mysql> select * from innodb_locks;
+----------------+-------------+-----------+-----------+-------------------+------------+------------+-----------+----------+------------------------+
| lock_id        | lock_trx_id | lock_mode | lock_type | lock_table        | lock_index | lock_space | lock_page | lock_rec | lock_data              |
+----------------+-------------+-----------+-----------+-------------------+------------+------------+-----------+----------+------------------------+
| 28275:1448:3:1 | 28275       | X         | RECORD    | `test`.`employee` | PRIMARY    |       1448 |         3 |        1 | supremum pseudo-record |
| 28273:1448:3:1 | 28273       | X         | RECORD    | `test`.`employee` | PRIMARY    |       1448 |         3 |        1 | supremum pseudo-record |
+----------------+-------------+-----------+-----------+-------------------+------------+------------+-----------+----------+------------------------+
2 rows in set, 1 warning (0.00 sec)

Se você alterar um pouco o caso de teste para que haja uma linha em employees para dept-id=2 e, em seguida, tentar adicionar um funcionário para dept-id=3, funcionará. Exemplo:
create table department (
    id bigint not null, 
    budget bigint not null, 
    name varchar(255), 
    primary key (id)
) ENGINE=InnoDB;

create table employee (
    id bigint not null, 
    name varchar(255), 
    salary bigint not null, 
    department_id bigint, primary key (id)
) ENGINE=InnoDB;


alter table employee 
add constraint FK_department_id 
foreign key (department_id) 
references department (id);


insert into department (name, budget, id) 
values ('Hypersistence', 100000, 1);

insert into department (name, budget, id) 
values ('Bitsystem', 10000, 2);

insert into department (name, budget, id) 
values ('XX', 10000, 3);


insert into employee (department_id, name, salary, id) 
values (1, 'John Doe 0', 30000, 0);

insert into employee (department_id, name, salary, id) 
values (1, 'John Doe 1', 30000, 1);

insert into employee (department_id, name, salary, id) 
values (2, 'John Doe 2', 30000, 2);


start transaction;

SELECT * 
FROM employee 
WHERE department_id = 1 
FOR UPDATE;


# new session

insert into employee (department_id, name, salary, id) 
values (3, 'Dave', 9000, 5)