文章目录
数据准备
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for emp
-- ----------------------------
DROP TABLE IF EXISTS `emp`;
CREATE TABLE `emp` (
`id` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
SET FOREIGN_KEY_CHECKS = 1;
insert into emp
values (1,"gaoxinfu11");
insert into emp
values(2,"gaoxinfu22");
insert into emp
values(3,"gaoxinfu33");
insert into emp
values(4,"gaoxinfu44");
1.InnoDB 存储引擎的锁
1.1.锁的类型 -八中类型
https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html
1.2.锁的基本模式
1.2.1.表锁
1.表锁,顾名思义,是锁住一张表;
1.2.2.行锁
1.行锁就是锁住表里面的一行数据。
1.2.3.关于行锁和表锁的粒度概述
1.锁的粒度主要是指加锁的数据范围;
2.表锁肯定是大于行锁的。
3.加锁效率,表锁也是大于行锁的;表锁只需要直接锁住这张表就行了,而行锁,还需要在表里面去检索这一行数据,所以表锁的加锁 效率更高。
4.表锁的冲突概率肯定是大于行锁的,
因为当我们锁住一张表的时候,其他任何一个事务都不能操作这张表。但是我们锁住了表里面的一行数据的时候,
其他的事务还可以来操作表里面的其他没有被锁定的行,所以表锁的冲突概率更大。
表锁的冲突概率更大,所以并发性能更低
1.3.锁的类型
1.3.1.Shared Locks (共享锁) ----->行级别的锁
1.3.1.1.概念
1.共享锁又称为读锁,简称S锁,顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改;
1.3.1.2.如何设置共享锁
select * from emp where id=1 LOCK IN SHARE MODE;
在share-mode-tx01这个事务中进行加锁
BEGIN;
select * from emp where id=1 LOCK IN SHARE MODE;
1.3.1.2.如何释放共享锁
commit或者rollback
1.3.1.3.案例1-查询加锁后查询
在share-mode-tx02事务中进行查询
BEGIN;
select * from emp where id=1 ;
结论
1.共享锁很明显,加锁之后,我们还是能够进行查询操作的;
1.3.1.3.案例2-查询加锁后更新
同样的share-mode-tx01事务中我们进行加锁之后,操作下面的事务
在share-mode-tx03事务中我们对同一条记录进行更新
BEGIN;
update emp set name='gaoxinfu-sm' where id=1;
1.同一条记录被加共享锁之后,因为被锁住,无法进行更新/删除等操作;
1.3.2.Exclusive Locks(排它锁)又称写锁或者X锁 ----->行级别的锁
1.3.2.1.概念
1.排他锁不能与其他锁并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的锁(共享锁、排他锁),
只有该获取了排他锁的事务是可以对数据行进行读取和修改。
1.3.2.2.如何设置排它锁
自动加锁 delete/update/insert
delete/update/insert 默认加上X锁;
手动加锁 FOR UPDATE
手动:select * from emp where id=1 FOR UPDATE;
1.3.2.3.如何释放排它锁 commit/rollback;
commit/rollback;
1.3.2.3.案例演示
在事务exclusive-mode-01中进行更新id=1的记录
begin;
update emp set name='gaoxinfu-x-mode' where id=1;
在事务exclusive-mode-02中进行再次更新id=1的记录
begin;
update emp set name='gaoxinfu-x-mode-02' where id=1;
1.很明显由于在事务exclusive-mode-01之中没有提交(没有结束)也就是排它锁加锁之中,所以在事务exclusive-mode-02之中再次
去更新的时候,不会成功;
1.3.3.意向锁
1.3.3.1.概念
1.首先意向锁是一个表锁,是对整个表的一个加锁操作;
2.意向锁包含两种:意向共享锁(Intention Shared Lock,简称IS锁)和意向排它锁(Intention Exclusive Lock)
3.意向锁是什么呢?我们好像从来没有听过,也从来没有使用过,其实他们是由数据 库自己维护的。
也就是说,
当我们给一行数据加上共享锁之前,数据库会自动在这张表上面加一个意向共享锁。
当我们给一行数据加上排他锁之前,数据库会自动在这张表上面加一个意向排他锁。
反过来讲:
如果一张表上面至少有一个意向共享锁,说明有其他的事务给其中的某些数据行加上了共享锁。
如果一张表上面至少有一个意向排他锁,说明有其他的事务给其中的某些数据行加上了排他锁。
1.3.3.1.如何设置意向锁
LOCK TABLES table_name WRITE/READ; #
1.3.3.2.意向锁的意义
第一个,我们有了表级别的锁,在 InnoDB 里面就可以支持更多粒度的锁。
第二个,我们想一下,如果说没有意向锁的话,当我们准备给一张表加上表锁的时候,我们首先要做什么?是不是必须先要去
判断有没其他的事务锁定了其中了某些行?如果有的话,肯定不能加上表锁。那么这个时候我们就要去扫描整张表才
能确定能不能成功加上一个表锁,如果数据量特别大,比如有上千万的数据的时候,加表锁的效率是不是很低?
但是我们引入了意向锁之后就不一样了。我只要判断这张表上面有没有意向锁,
如果有,就直接返回失败。
如果没有,就可以加锁成功。
所以InnoDB里面的表锁,我们可以把它理解成一个标志。就像火车上厕所有没有人使用的灯,是用来提高加锁的效率的。
1.3.3.3.意向锁使用场景
1.3.3.4.案例演示- 行锁之后进行表锁试验
在事务intention-mode-01这个事务中我们先手动加锁(排它锁)
BEGIN;
select * from emp where id=1 for update;
在intention-mode-02事务中对表进行加意向锁
BEGIN;
LOCK TABLES emp WRITE;
1.如上一旦如果表里记录有如果有被锁定的,那么我们去加表锁的话,是无法成功的;
1.3.3.5.案例演示- 表锁之后进行行锁试验
我们先在intention-mode-02这个事务之中先进行表的加锁
BEGIN;
LOCK TABLES emp WRITE;
然后在intention-mode-01这个事务中进行对记录id=1加锁
BEGIN;
select * from emp where id=1 for update;
1.如上表一旦被锁定,是无法进行行锁的
1.3.3.6.解锁
UNLOCK TABLES;
1.4.
来源:CSDN
作者:东山富哥
链接:https://blog.csdn.net/u014636209/article/details/104114296