Home > Software engineering >  Why does innodb lock more records when range deletion
Why does innodb lock more records when range deletion

Time:01-02

I am using mysql innodb database. I thought I had understood the locking mechanism of mysql. But I found an example, which conflicts with my understanding.See the example below (verified in version 5.7.32 with rc isolation level).

create table

Create Table: CREATE TABLE `ep` (
  `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT '',
  `e_id` int(11) NOT NULL COMMENT '',
  `name` varchar(255) NOT NULL COMMENT '',
  `create_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '',
  `update_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '',
  PRIMARY KEY (`id`),
  KEY `idx_e_id` (`e_id`) USING BTREE,
  KEY `idx_create_at` (`create_at`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8

initial data

insert into ep(e_id, name, create_at) values(100, 'shijie', '2022-12-01 00:00:00'),(100, 'jianfeng', '2022-12-02 00:00:00'),(100, 'syx', '2022-12-03 00:00:00');

Before the next case testing, there are 3 records in the ep table.

 id: 1
 e_id: 100
 name: shijie
 create_at: 2022-12-01 00:00:00
 update_at: 2023-01-01 05:31:13

 id: 2
 e_id: 100
 name: jianfeng
 create_at: 2022-12-02 00:00:00
 update_at: 2023-01-01 05:31:13

 id: 3
 e_id: 100
 name: syx
 create_at: 2022-12-03 00:00:00
 update_at: 2023-01-01 05:31:13
  • test case 1

concurrent transactions

Session1 Session2 Locks
begin; begin;
insert into ep(e_id, name, create_at) values(100, 'stt', '2022-12-04 00:00:00');
insert into ep(e_id, name, create_at) values(100, 'ssd', '2022-12-04 00:00:00');
select * from ep\G;

id: 1
e_id: 100
name: shijie
create_at: 2022-12-01 00:00:00
update_at: 2023-01-01 05:31:13

id: 2
e_id: 100
name: jianfeng
create_at: 2022-12-02 00:00:00
update_at: 2023-01-01 05:31:13

id: 3
e_id: 100
name: syx
create_at: 2022-12-03 00:00:00
update_at: 2023-01-01 05:31:13

id: 4
e_id: 100
name: stt
create_at: 2022-12-04 00:00:00
update_at: 2023-01-01 05:41:47
select * from ep\G;

id: 1
e_id: 100
name: shijie
create_at: 2022-12-01 00:00:00
update_at: 2023-01-01 05:31:13

id: 2
e_id: 100
name: jianfeng
create_at: 2022-12-02 00:00:00
update_at: 2023-01-01 05:31:13

id: 3
e_id: 100
name: syx
create_at: 2022-12-03 00:00:00
update_at: 2023-01-01 05:31:13

id: 5
e_id: 100
name: ssd
create_at: 2022-12-04 00:00:00
update_at: 2023-01-01 05:44:46
delete from ep where e_id=100 and create_at <= '2022-12-03 00:00:00'; lock waiting

SHOW ENGINE INNODB STATUS OUTPUT

  • test case 2

concurrent transactions

Session1 Session2 Locks
begin; begin;
insert into ep(e_id, name, create_at) values(100, 'stt', '2022-12-04 00:00:00');
insert into ep(e_id, name, create_at) values(100, 'ssd', '2022-12-04 00:00:00');
select * from ep\G;

id: 1
e_id: 100
name: shijie
create_at: 2022-12-01 00:00:00
update_at: 2023-01-01 05:31:13

id: 2
e_id: 100
name: jianfeng
create_at: 2022-12-02 00:00:00
update_at: 2023-01-01 05:31:13

id: 3
e_id: 100
name: syx
create_at: 2022-12-03 00:00:00
update_at: 2023-01-01 05:31:13

id: 4
e_id: 100
name: stt
create_at: 2022-12-04 00:00:00
update_at: 2023-01-01 05:41:47
select * from ep\G;

id: 1
e_id: 100
name: shijie
create_at: 2022-12-01 00:00:00
update_at: 2023-01-01 05:31:13

id: 2
e_id: 100
name: jianfeng
create_at: 2022-12-02 00:00:00
update_at: 2023-01-01 05:31:13

id: 3
e_id: 100
name: syx
create_at: 2022-12-03 00:00:00
update_at: 2023-01-01 05:31:13

id: 5
e_id: 100
name: ssd
create_at: 2022-12-04 00:00:00
update_at: 2023-01-01 05:44:46
delete from ep where e_id=100 and create_at <= '2022-12-02 00:00:00'; no lock waiting

SHOW ENGINE INNODB STATUS OUTPUT

  • question

In test case 1, when the deletion range of create_at is large, session1 tries to acquire the primary key lock of session2 inserting data(id=5). In fact, the data inserted in session2 is out of the deletion range of create_at in session1.

In test case 2, reduce the deletion range of create_at(2022-12-03 00:00:00 -> 2022-12-02 00:00:00), and session 1 will no longer acquire any locks of the data inserted by session 2(neither the primary key lock nor the secondary index lock).

In fact, when deleting according to the primary key index range, such as delete from ep where id <= id_num, there also has the problem of large-scale deletion to obtain more lock inserted by other concurrent sessions and small-scale deletion not to obtain more lock.

Can anyone explain the cause of this problem or provide related articles.

CodePudding user response:

MySQL locks the rows it looks at during execution (and potentially frees them again).

In your case, based on the behaviour, for the second test case, MySQL uses the index on create_at to find the rows, for the first case, it doesn't.

So for your second delete, MySQL will not even look at ids 4 and 5 (because they are outside of the date range), and thus doesn't have to wait for locks on ids 4 and 5.

For your first delete, MySQL doesn't use the index, but either the primary key or the index on e_id, and thus has to wait for the lock.

Repeat the experiment without the index, and it might match your understanding (although you didn't actually specify what you did expect).

CodePudding user response:

Replace idx_e_id with

INDEX(e_id, created_at)

So that there will be a useful index for the DELETE.

  • Related