您的位置:首页 > 科技 > IT业 > 网络推广的主要工作内容_seo导航站_seo教程网站优化_一级消防工程师考试

网络推广的主要工作内容_seo导航站_seo教程网站优化_一级消防工程师考试

2025/4/3 15:08:27 来源:https://blog.csdn.net/Bonnie_1215/article/details/146886232  浏览:    关键词:网络推广的主要工作内容_seo导航站_seo教程网站优化_一级消防工程师考试
网络推广的主要工作内容_seo导航站_seo教程网站优化_一级消防工程师考试

1 锁的粒度

        MyISAM只支持表锁,而InnoDB同时支持表锁和行锁。表锁和行锁的区别到底在哪里?
锁定粒度:表锁  > 行锁
加锁效率:表锁 > 行锁
冲突概率:表锁 > 行锁
并发性能: 表锁 < 行锁
表锁锁粒度大,加锁快,锁的并发性能低,而行锁锁粒度小,加锁慢,锁的并发性能高。

2、锁类型

        两个行级别锁(Shared andExclusive Locks)和两个表级别锁(Intention Locks)成为锁的基本模式;后面三个 Record Locks、Gap Locks、Next-KeyLocks,我们把它们叫做锁的算法也就是分别在什么情况下锁定什么范围。
        插入意向锁:是一种特殊的间隙锁。间隙锁不允许插入数据,但是插入意向锁允许多个事务同时插入数据到同一个范围。比如(4,7),一个事务插入5,一个事务插入6,不会发生锁等待。
        自增锁:是一种特殊的表锁,用来防止自增字段重复,数据插入以后就会释放,不需要等到事务提交才释放,如果需要选择更快的自增值生成速度或者更加连续的自增值,就要通过修改自增锁的模式改变。

SHOW VARIABLES LIKE 'innodb_autoinc_lock_mode';
-- 0: traditonal(每次都会产生表锁)
-- 1:consecutive(会产生一个轻量锁,simpleinsert 会获得批量的锁,保证连续插入,默认值)
-- 2:interleaved(不会锁表,来一个处理一个,并发最高)

Predicate Locks for Spatial Indexes 是 5.7 版本里面新增的一种数据类型的索引的锁。

3、共享锁

        第一个行级别的锁就是我们在官网看到的Shared Locks(共享锁),我们获取了一行数据的读锁以后,可以用来读取数据,所以叫做读锁,注意不要在加上了读锁以后去写数据,不然的话可能会出现死锁的情况。而且多个事务可以共享一把锁。
        共享锁的作用:因为共享锁会阻塞其他事务的修改,所以可以用在不允许其他事务修改数据的情况。
        给一行数据加锁:select .... lock in share mode;的方式手工加上一把读锁。
         锁释放有两种方式,只要事务结束,锁就会自动释放,包括提交事务和结束事务。
        案例:

Transaction1Transaction2
begin;
select * from user where id=1 lock in share mode;
begin;
select * from user where id=1 lock in share mode;
// 正常执行

4 排他锁

        第二个行级别的锁叫做Exclusive Locks(排他锁),它是用来操作数据的,所以又叫做写锁。主要一个事务获取了一行数据的排他锁,其他的事务就不能再获取这一行数据的共享锁和排它锁。|
        排它锁有两种加锁方式,第一种是自动加排他加锁,我们在操作数据库的时候包括增删改,都会默认加上排它锁。另外一种是手动加排它锁,FOR UPDATE给一行数据加上一行排它锁,这种方式在写SQL或者在代码中都是比较常用的方式。
        案例:

Transaction1Transaction2
begin;
update user set name="bonnie"  where id=1;
begin;
select * from user where id=1 lock in share mode;  // BLOCKED
select * from user where id=1 for update;  // BLOCKED
delete from user where id=1;// BLOCKED

5、意向锁

        当我们给一行数据加上共享锁之前,数据库就会自动在这张表上面加一个意向共享锁。
        当我们给一行数据加上排他锁之前,数据库就会自动在这张表上面加一个意向排他锁。
      反之:
        如果一张表上面至少有一个意向共享锁,说明有其他事务给其中的某些数据行加上了共享锁,如果一张表上面至少有一个意向排他锁,说明有其他的事务给其中的某些数据行加上了排他锁。
        意向锁跟意向锁是不冲突的,意向锁跟行锁也不冲突。
举个例子说明两个表(意向共享锁、意向排他锁)级别的锁存在的意义:
        如果没有意向锁的话,当我们准备给一张表加上表锁的时候,我们首先要去判断有没有其他的事务锁定了其中了某些行,如果有的话,肯定不能加上表锁。那么这个时候我们需要去扫描整张表才能确定能不能成功加上一个表锁,如果数据量特别大, 比如有上千万、上亿数据的时候,加锁的效率就会变的很低。
        但是有了意向锁之后,就不用扫描整张表看哪行有加锁行锁,我们只需要判断这张表上是否有意向锁,如果有,就直接返回失败。如果没有,就可以加锁成功。所以InnoDB里面的表锁,我们可以简单理解成一个标志。就像高铁上的卫生间,没有灯表示卫生间没有人使用,灯亮表示用人使用。本质其实就是提高加锁的效率

Transaction1Transaction2
begin;
select * from user where id=1 for update;
begin;
lock tables user write; // block
unlock tables; // 释放锁

锁的作用:跟java里面的锁是一样的,是为了解决资源竞争的问题,Java里面的资源是对象,数据库的资源就是数据表或者数据行。所以锁是用来解决事务对数据的并发访问的问题。

6 行锁的原理

6.1 没有索引的表

首先我们有三张表,一张表没有索引的t1,一张有主键索引的t2,一张有唯一索引的t3。
我们假设InnoDB的行锁锁住了是一行数据或者一条记录。
t1表,有id(int)  name(varchar)字段,有4条记录1 2 3 4

Transaction1Transaction2
begin;
select * from t1 where id=1 for update;
select * from t1 where id=3 for update  // blocked
insert into t1 values(5, '5') // blocked

我们在两个会话里面手工开启两个事务:
        在第一个事务里面,我们通过where id=1 锁住了第一行数据
        在第二个事务里面,我们通过where id=3 这行数据加锁会发现加锁是失败的,被阻塞。
        然后再插入一条不存在的记录5,它也会被阻塞。实际上整张表都被锁住了,所以在没有索引的情况下InnoDB的行锁锁住的不是行记录是整张表。

6.2 有主键索引的表

 假设t2的表结构,id(主键索引) name, 里面的数据有1 4 7 10。

Transaction1Transaction2
begin;
select * from t2 where id=1 for update;
select * from t2 where id=1 for update // blocked
select * from t2 where id=4  for update // ok

 第一种情况,使用相同的id值去加锁,冲突;使用不同的id加锁,可以加锁成功,那么既然不是锁定一行数据,有没有可能是锁住了id的这个字段呢?

6.3 唯一索引

假设t3的表结构,字段还是一样的,id上创建了一个主键索引,name上创建了一个唯一索引,里面的数据有1 4 7 10

Transaction1Transaction2
begin;
select * from t3 where name='4' for update;
select * from t3 where name='4' for update; // blocked
select * from t3 where id=4 for update; // blocked

在第一个事务里面,通过name='4', 锁定值是4的这行数据。
在第二个事务里面,尝试获取一样的排他锁,肯定是失败的,尝试id=4加锁也是失败的;
既然锁住的不是record也不是column,Innodb的行锁住的到底是什么?通过上面的三个案例:InnoDB的行锁,就是通过锁住索引来实现的
那我们还有两个问题没有解决
1、为什么表里面没有索引的时候,锁住一行数据会导致锁表?
或者说,如果锁住的是索引,一张表没有索引怎么办?
所以,一张表有没有可能没有索引?
1)如果我们定义了主键(PRIMARY KEY),那么 InnoDB 会选择主键作为聚集索引。
2)如果没有显式定义主键,则 InnoDB 会选择第一个不包含有 NULL 值的唯一索引作为主键索引。
3)如果也没有这样的唯一索引,则 InnoDB 会选择内置6 字节长的 ROWID 作为隐藏的聚集索引,它会随着行记录的写入而主键递增所以,为什么锁表,是因为查询没有使用索引,会进行全表扫描,然后把每一个隐藏的聚集索引都锁住了。
2、为什么通过唯一索引给数据行加锁,主键索引也会被锁住?
大家还记得在 InnoDB 里面,当我们使用辅助索引的时候,它是怎么检索数据的吗?
辅助索引的叶子节点存储的是什么内容?
在辅助索引里面,索引存储的是二级索引和主键的值。比如 name=4,存储的是name的索引和主键 id 的值 4。
而主键索引里面除了索引之外,还存储了完整的数据。所以我们通过辅助索引锁定一行数据的时候,它跟我们检索数据的步骤是一样的,会通过主键值找到主键索引,然后也锁定
本质上是因为锁定的是同一行数据,是相互冲突的。

7 锁的算法


 在数据库中存在的主键值,我们把它叫做record(记录),上图中有4个记录 1 4 7 10;
根据主键,这些存在的Record隔开的数据不存在区间,叫做Gap,间隙,左开右开的区间;
假设有N个Record,那么所有的数据会被划分成N+1个Gap;
Next-key: 间隙(Gap)连同左边的记录(Record),叫做临键的区间,它是一个左开右闭的区间。

7.1 记录锁

当我们对唯一性的索引(主键、唯一索引)使用等值查询,精确匹配到一条记录的时候,这个时候使用的就是记录锁。

7.2 间隙锁

当我们查询的记录不存在,没有命中任何一个record,无论是用等值还是范围查询的时候,使用的都是间隙锁。

 案例:where id>4 and id<7   where id=6

Transaction1Transaction2
select * from t1 where id=6 for update;
insert into t2 values(5, '5'); // blocked
insert into t2 values(6, '6'); // blocked
select * from t2 where id=6 for update; // ok
select * from t1 where id>20 for update;
insert into t2 value(11, '11'); // blocked

间隙锁主要是阻塞插入insert。想同的间隙锁之间不冲突。 

7.3  临键锁

        第三种情况,当我们使用了范围查询,不仅仅命中了 Record 记录,还包含了Gap间隙,在这种情况下我们使用的就是临键锁,它是 MVSQL 里面默认的行锁算法,相当于记录锁加上间隙锁。
唯一性索引,等值查询匹配到一条记录的时候,退化成记录锁。
没有匹配到任何记录的时候,退化成间隙锁。

Transaction1Transaction2
begin;
select * from t1 where  id>5 and id<9 for update;
begin;
select * from t1 where id=4 for update; // ok

insert into t1 value(6, '6'); // blocked
insert into t1 value(8, '8'); // blocked

select * from t1 where id=10 for update;  // blocked

7.4 隔离级别实现

事务隔离级别脏读不可重复读幻读
未提交读可能可能可能
提交读        不可能可能可能
可重复读不可能不可能对Innodb不可能
串行化不可能不可能不可能

未提交读:不加锁
提交读普通的select使用的是快照读,底层mvcc实现
                加锁的select使用的都是记录锁,因为没有Gap Lock;
                除了两种特殊情况--外键约束检査(foreign-key constraint checking)以及重复键检査 
                (duplicate-key checking)时会使用间隙锁封锁区间。所以 RC 会出现幻读的问题。
可重复读:普通的select使用的是快照读,底层使用mvcc实现
                加锁的select(select..in shard mode / select ..for update)以及更新语句使用的是当前读,
                底层使用记录锁、间隙锁、临键锁
串行化:所有的select语句都会隐式的转化为select.....in share mode,会和update、delete互斥

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com