1、锁的概念
锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算资源(如 CPU、RAM、I/O等)的争用以外,数据也是一种共享的资源。如何保证数据并发访问的一致性、 有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。 因此,锁对数据库而言显得尤其重要,也更加复杂。
相对其他数据库而言,MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制。按照锁的粒度来划分,可以分为表锁、行锁和页锁。
2、MyISAM的表锁
MyISAM存储引擎只支持表锁。
在 执行查询操作(select)前, 会自动给涉及的所有表加读锁;
在 执行更新操作(insert、update、delete等)前, 会自动给涉及的所有表加写锁。
说明:
1)MyISAM表的读操作,不会阻塞其他用户对相同表的读操作,但会阻塞对相同表的写操作;
2)MyISAM表的写操作,会阻塞其他用户对相同表的读操作、写操作;
3)MyISAM表的读、写操作之间,以及写操作之间是串行的。
3、InnoDB的行锁
InnoDB存储引擎既支持行锁,也支持表锁,但默认情况下是采用行锁。
InnoDB的行锁是通过锁定索引项来实现的,而不是锁定物理行记录。InnoDB的锁,与索引、事务的隔离级别有关。
InnoDB的锁类型有很多种,这也是需要我们重点掌握的。
参考:https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html#innodb-record-locks
4、 测试数据
create table bank_myisam(id int not null auto_increment primary key,name varchar(30) comment '姓名',age int comment '年龄',balance decimal(18, 2) comment '余额')engine=myisam default charset=utf8;insert into bank_myisam(name, age, balance) values('zhangsan', 22, 1000);insert into bank_myisam(name, age, balance) values('lisi', 18, 2000);insert into bank_myisam(name, age, balance) values('wangwu', 20, 3000);insert into bank_myisam(name, age, balance) values('zhaoliu', 21, 4000);insert into bank_myisam(name, age, balance) values('tom', 19, 5000);insert into bank_myisam(name, age, balance) values('jack', 24, 6000);insert into bank_myisam(name, age, balance) values('lilei', 22, 7000);insert into bank_myisam(name, age, balance) values('lily', 18, 8000);
5、 演示MyISAM表锁
# myisam的表锁
# bank_myisam表加读锁
lock tables bank_myisam read;
select * from bank_myisam;
unlock tables;
# myisam的表锁
select * from bank_myisam;
update bank_myisam set balance = balance + 100 where id = 1;
6 、演示InnoDB行锁
# 事务A
# InnoDB的行锁
# insert、update、delete自动加锁
begin;
select * from bank_innodb;
# 手动加写锁
select * from bank_innodb where id = 2 for update;
commit;
# 事务B
# InnoDB的行锁
begin;
select * from bank_innodb;
update bank_innodb set balance = balance + 200 where id = 2;
commit;
