![cd4a923ec339026b5dd842ebffd45db0.png](https://i-blog.csdnimg.cn/blog_migrate/42c479d75216a033e0a816f30c3fc62c.jpeg)
在MySQL中不同的存储引擎支持不同的锁。按照锁的粒度来划分,可以分为表锁、行锁和页锁。
![7d4b537395aab60838d47735d6ea0f40.png](https://i-blog.csdnimg.cn/blog_migrate/6198354787f171ec09e5dea79dee7411.png)
MyISAM只支持表锁,InnoDB支持表锁和行锁,而BDB支持表锁和页锁
表锁:顾名思义,锁的是整个表
行锁:锁的是一条记录
页锁:mysql中数据是按页存储的,一页存满,就存储在下一页。而页锁就是锁定整个页
MyISAM的表锁
MyISAM存储引擎只支持表锁。
在执行查询操作(select)前, 会自动给涉及的所有表加读锁;
在 执行更新操作(insert、update、delete等)前, 会自动给涉及的所有表加写锁。
![cd89f4e6f7051ac5a6cd116187ca1130.png](https://i-blog.csdnimg.cn/blog_migrate/3fb8042cf61e58eef1c79f45f5d9b5e0.png)
说明:
1)MyISAM表的读操作,不会阻塞其他用户对相同表的读操作,但会阻塞对相同表的写操作;
2)MyISAM表的写操作,会阻塞其他用户对相同表的读操作、写操作;
3)MyISAM表的读、写操作之间,以及写操作之间是串行的。
示例演示:
表创建和数据插入:
create
模拟读锁
1. 窗口1通过读锁锁表
![35bbcc83bfc23791cbacd21e868b592d.png](https://i-blog.csdnimg.cn/blog_migrate/681767f08925a962be34cd5c26ddd0de.png)
2. 窗口2搜索该表数据
![2df9684fc68745c456043465b02afba9.png](https://i-blog.csdnimg.cn/blog_migrate/9bc42d2ef1d1a99390923d7c6fc144f9.png)
3. 窗口2修改id为1的数据(阻塞中)
![42bf18223af0a05952dbbc37206f49b2.png](https://i-blog.csdnimg.cn/blog_migrate/876d77f2344dff2976e4a5806fcc2443.png)
4. 窗口1解锁改表
![24b6d6d2279c9238bc71711878d76b48.png](https://i-blog.csdnimg.cn/blog_migrate/e10757e64639f7b67ef4cfb05aed9fc5.png)
5. 窗口2自动解阻塞,执行步骤3中的命令
![9fb2d1c6f4e5a4d654644045b8326399.png](https://i-blog.csdnimg.cn/blog_migrate/d659fb63abb9f17cc6ae6649246bfe97.png)
模拟写锁
1.窗口1通过写锁锁表
![a7bbf12cb3ff581b51eddf2278844196.png](https://i-blog.csdnimg.cn/blog_migrate/5fc191732a74148f347b5f1dae38cb91.png)
2. 窗口2查询表数据(阻塞)
![4bca42d9cf27ddcf12a59184fde8f835.png](https://i-blog.csdnimg.cn/blog_migrate/5b313db4509078e38c694798a45507a6.png)
3. 窗口1解锁表
![b650094cf9979d1fbaff2b20880eabf2.png](https://i-blog.csdnimg.cn/blog_migrate/f28575dae0d1fbc0991f2c86ab79d57e.png)
4. 窗口2自动执行阻塞的命令
![e5188ba5db2a7688a5f8961051d7c1e1.png](https://i-blog.csdnimg.cn/blog_migrate/b441c2f3c920babe38c8c833fb254f32.png)
InnoDB的行锁
InnoDB存储引擎既支持行锁,也支持表锁,但默认情况下是采用行锁。InnoDB的行锁是通过锁定索引项来实现的,而不是锁定物理行记录。InnoDB的锁,与索引、事务的隔离级别有关。InnoDB 的锁类型有很多种
![4b4606890187a9597bbf1c126991388d.png](https://i-blog.csdnimg.cn/blog_migrate/6439cf83b52190c6fd4d46faf6487663.png)
1. 共享锁:当一个事务对某行记录上了共享锁,允许其他事务对 该记录进行读操作,但不允许写操作。
#共享锁加锁方式
SELECT ... LOCK IN SHARE MODE
![13ce1dcaa5aa4bb7d0999e0160a81ed8.png](https://i-blog.csdnimg.cn/blog_migrate/e80d7932d3928696a13765005403fe80.png)
示例演示:
创建数据:
create table bank_innodb(
id int not null auto_increment primary key,
name varchar(30) comment '姓名',
age int comment '年龄',
balance decimal(18, 2) comment '余额'
)engine=InnoDB default charset=utf8;
insert into bank_innodb(name, age, balance) values('zhangsan', 22, 1000);
insert into bank_innodb(name, age, balance) values('lisi', 18, 2000);
insert into bank_innodb(name, age, balance) values('wangwu', 20, 3000);
insert into bank_innodb(name, age, balance) values('zhaoliu', 21, 4000);
insert into bank_innodb(name, age, balance) values('tom', 19, 5000);
insert into bank_innodb(name, age, balance) values('jack', 24, 6000);
insert into bank_innodb(name, age, balance) values('lilei', 22, 7000);
insert into bank_innodb(name, age, balance) values('lily', 18, 8000);
1. 事务A创建共享锁
![096ce89bde82035a74303e5beffedf8c.png](https://i-blog.csdnimg.cn/blog_migrate/5183b4edc9c99dddae4d3151f3d66d66.png)
2. 事务B创建共享锁(执行成功)
![e5199efb3c3f4abb5c405ac5450f8ce9.png](https://i-blog.csdnimg.cn/blog_migrate/614bc84baaad3ae90c6aba65f8a8b218.png)
3. 事务B执行修改操作(阻塞)
![e08d0f5bdf120c512faff75179fdba5f.png](https://i-blog.csdnimg.cn/blog_migrate/3671156c8d24e372b92a62cd45e2fc27.png)
4. 事务A结束事务
![dfda024e03539d295fc71aaeb4eb8fa0.png](https://i-blog.csdnimg.cn/blog_migrate/e82da56273e13da0bd4e853619b74ca8.png)
5. 事务B自动执行阻塞的任务
![6b751a6023c9311ec1335fd487357ed5.png](https://i-blog.csdnimg.cn/blog_migrate/e333792cc7cb5064b6beed96e9214d1b.png)
2.排他锁:当一个事务对某行记录上了排他锁,其他事务即 不能对该行记录进行读操作,也不能进行写操作。InnoDB会自动对增删改操作加排他锁。
#手动给查询语句加排他锁
SELECT ... FOR UPDATE
![655fa39f71232b75d9d1252bb139f5cf.png](https://i-blog.csdnimg.cn/blog_migrate/1bf17ad5392a87d52b8c88b70e286202.png)
示例演示:
1. 事务A加排他锁
![327d5a70ca6fcb0ac63c2a0608820d27.png](https://i-blog.csdnimg.cn/blog_migrate/f38b2912a40d64c33b8108ecb038b93e.png)
2. 事务B加共享锁(阻塞)
![62c2a0bd5d20880c62f474105feeeb27.png](https://i-blog.csdnimg.cn/blog_migrate/871191849aab053033b712c0d5a74574.png)
3. 事务A提交
![c5617c608fca220057eeeca1af6a7040.png](https://i-blog.csdnimg.cn/blog_migrate/c58bd06af7e87a38ddc9fe489a17eec6.png)
4. 事务B自动执行阻塞的任务
![a96cbddc1ec8a42e4b5d736a0778b21c.png](https://i-blog.csdnimg.cn/blog_migrate/e65a1be766df390d060e9a637d93513c.png)
自增锁:是当向含有AUTO_INCREMENT列的表中插入数据时需要获取的一种特 殊的表级锁。在最简单的情况下,如果一个事务正在向表中插入值,则任何其他事务必须等待对该 表执行自己的插入操作,以便第一个事务插入的行的值是连续的。
InnoDB还提供了参数 innodb_autoinc_lock_mode 用于设置自增锁模式,它可以对插入操作实现 性能与并发的平衡。
取值说明:
0:traditional,传统锁模式,语句级锁,保证值分配的可预见性、连续性、可重复性,保证主从复制的一致性。
1: consecutive,连续锁模式,锁在语句得到值后就释放,并发插入性能优于传统模式,MySQL 5.x默认模式。
2:interleaved,交错锁模式,最快最具扩展性的模式,基于binlog的复制与恢复不安全,MySQL 8.0默认模式。
为什么主键通常使用自增?
主要原因有两个:
1)索引本身是有序的,再加上MySQL底层是以页为单位来存储数据的,一页写满继续写下一页。如果使用非自 增id,为了保证索引的有序性,每次插入都需要将数据移动到合适的位置,可能会造成页分裂,影响插入性能。
2)相对而言,字符串作为主键占用的空间大,而且字符串的比较更慢。
分享几本学习mysql的书籍: