美文网首页
事务隔离与锁与索引

事务隔离与锁与索引

作者: RedHatMe | 来源:发表于2018-09-01 01:54 被阅读0次

隔离级别

之所以会有事务隔离一说,是由于不同事务的执行并不是串行化,而是并发的。所以事务才会 有不同的隔离级别的说法。

比如 未提交读,这个隔离级别 就会引发读脏数据。即 一个事务读了另一个事务未提交的数据,一旦另一个事务回滚。那这个事务读的就是脏数据。

比如 提交读 , 这个隔离级别 会出现不可重读现象。就是一个事务中,由于另外一个事务在这期间执行了insert 或者update delete操作 ,导致这个事务 前后读同一条记录读到的数据就不一致。更别提范围读了。
为啥呢,就是因为锁的原因。如果一个事务第一次读操作是select for update 直接弄上了行锁,那其他的事务不管怎么都没法改这行记录了,第一个事务再次发生读操作时,数据还是原来的数据。就不会出问题了。

比如 可重复读,当然就是说 在一个事务中 读某条记录读第一次 和第二次没差别。就是说其他事务的插入是被禁止的。但是 还是无法防止幻读。因为事务里面的select并没有加范围锁。

串行化 隔离级别当然可以防止任何问题,但是效率低下。所以当然不采用。所以Mysql默认级别是可重复读。这隔离级别已经很高了。

比如有表t:

   id name age
    1 zw  25
    4 mm 18
    6  zz   8

先是三个基本锁:
记录锁 锁定索引记录;

注意,InnoDB的行锁是实现在索引上的,而不是锁在物理行记录上。潜台词是,如果访问没有命中索引,也无法使用行锁,将要退化为表锁。

间隙锁 锁定间隔,防止间隔中被其他事务插入;
(1,4) (4,6)

临键锁 锁定索引记录+间隔,(还包括第一条记录之前 和 最后一条记录之后)防止幻读;
(-无穷,1)[1,4) [4,6) [6,+无穷)

然后再看其他锁:

乐观锁

程序自己实现,一般的实现乐观锁的方式就是在数据库多放一个字段记录数据版本version。
实现数据版本有两种方式,
第一种是使用版本号,

第二种是使用时间戳。

悲观锁

for udate 排他锁

在事务开始后,使用排他锁的目的 是为了后续执行update修改。正如它的名字for update 一样。
这种锁是强一致性锁,就是说:
事务A执行了select id from t where status = 2 for update(status是锁引,则在该行记录加行锁,如果status 不是索引,那加的就是表锁了),
事务B再执行select id from t where status = 2 for update 时,是阻塞的。
事务C执行 select id from t where status = 2 lock in share mode时。也是阻塞的。
但是 如果执行select id from t where status = 2 时,不阻塞。
因为Innodb引擎默认的select 是不加锁的,直接读取已提交的事务保存的快照版本数据。
Innodb引擎默认的delete update操作是加了排他锁的。这样就保证了强一致性。

这种强一致性 就是保证了只有一个事务在执行修改。

lock in share mode 共享锁

事务A执行 select id from t where status = 2 lock in share mode时。
事务B执行 select id from t where status = 2 lock in share mode时,是可行的。
事务C执行 select id from t where status = 2 for update时。是阻塞的。
但是事务D执行 update/delete 操作 是阻塞的。
事务E执行 insert 操作 是不阻塞的。这个按道理也是不阻塞的。

---引用原话:
画外音:

  1. 排它锁是很强的锁,不与其他类型的锁兼容。这也很好理解,修改和删除某一行的时候,必须获得强锁,禁止这一行上的其他并发,以保障数据的一致性。

  2. 为了保证数据强一致,InnoDB使用强互斥锁,保证同一行记录修改与删除的串行性;

3.InnoDB使用插入意向锁,可以提高插入并发;讲解见下。

插入意向锁:

insert 操作是个特殊的操作,比如存在插入意向锁这种锁 )
假设有表,在MySQL,InnoDB,RR下:

t(id unique PK, name);
10, shenjian
20, zhangsan
30, lisi

事务A先执行,在10与20两条记录中插入一行,还未提交:
insert into t values(11, xxx);
事务B后执行,也在10与20两条记录中插入一行:
insert into t values(12, ooo);
事务B是不阻塞的。
因为插入意向锁,相同索引区间,insert 进入不同行,所以就不会相互阻塞了。

索引

MyISAM 和InnoDB 索引分类:

InnoDB的索引有两类索引,聚集索引(Clustered Index)与普通索引(Secondary Index)
聚集索引 是一定存在的 且以主键作为索引,
没有表主键 会自动采用其他非重复列,
再咩有mysql内部也会自己创建一个id列。
普通索引 就是 辅助索引。如果用辅助索引查,则走两遍索引,
先查辅助索引 查主键
再根据聚集索引,查记录。
如 select * from t where name = "zw";
MyISAM也是有两类索引。叫非聚集索引,辅助索引。
非聚集索引类似InnoDB 聚集索引,辅助索引类似InnoDB辅助索引。

MyISAM 和InnoDB 索引的区别:

MyISAM 索引
InnoDB索引

区别就是:

  1. MyISAM 索引文件 和 表记录数据 是单独分开的。由索引最后叶子节点里面主键对应的地址去表记录找。
  2. InnoDb 是直接索引结构最后叶子节点放的就是一条记录数据。

Mysql 和ISAM区别:
MyISAM不支持事务,不支持行锁 ,只有表锁,支持全文索引。

索引实现原理

直接看图


二叉搜索树
B-树
B+树

总结就是:
1. 二叉搜索层多。只有二叉。
2. B-树非叶子节点 叶节点 包含一整条记录数据 和指针。
而B+树 只是 叶子节点才带一整条记录,其他非叶子节点只带了key。
这样就能保证
1. 如果按页加载一页4K的数据,能从磁盘多加载很多key进入内存。从而减少磁盘IO。
2. 另外 B+树 最后叶子节点连成了链表结构。方便了范围查询。就是说只要从索引找范围的两端,找到两条记录。通过链表就完全确定了中间数据。

引用:
https://mp.weixin.qq.com/s/YMbRJwyjutGMD1KpI_fS0A
http://blog.codinglabs.org/articles/theory-of-mysql-index.html

相关文章

  • 事务隔离与锁与索引

    隔离级别 之所以会有事务隔离一说,是由于不同事务的执行并不是串行化,而是并发的。所以事务才会 有不同的隔离级别的说...

  • 【学习】MySQL数据库

    存储引擎 存储引擎 索引 InnoDB索引原理索引 锁 锁不同Select加锁分析 事务 事务事务隔离级别XAMV...

  • MySQL 基本概念

    MyISAM:无事务、锁表、读写互相阻塞、索引不缓存数据、数据与索引分离,都是【非聚集索引】InnoDB:有事务,...

  • 收藏-MySQL

    # MySQL的并发控制与加锁分析# MySQL的四种事务隔离级别# mysql共享锁与排他锁

  • Mysql锁与事务隔离级别

    锁的定义 锁是协调多个进程或线程访问某一共享可变资源,防止并发造成不可预见性的问题 锁分类 性能上分为乐观锁(版本...

  • 深入理解InnoDB -- 锁篇

    锁是实现事务隔离性最广泛使用的技术。本文主要分享InnoDB中锁的设计与实现。 锁的定义 下面列举innodb支持...

  • 深入理解InnoDB -- 锁篇

    锁是实现事务隔离性最广泛使用的技术。本文主要分享InnoDB中锁的设计与实现。 锁的定义 下面列举innodb支持...

  • Innodb存储引擎--锁整理

    Innodb的锁,保障了事务的隔离性;对索引(聚集索引组织表)加锁,Oracle是对数据块(堆表)加锁 何登成的文...

  • 事务 与 事务隔离

    事务就是要保证一组数据库操作,要么全部成功,要么全部失败。再MySQL中,事务支持是在引擎层实现的。MySQL是一...

  • 【重学MySQL打卡行动】Day3事务隔离:为什么你改了我还看不

    学习内容 : 事务隔离级别与实现 一、隔离性与隔离级别 1.事务的特性:原子性、一致性、隔离性、持久性2.多事务同...

网友评论

      本文标题:事务隔离与锁与索引

      本文链接:https://www.haomeiwen.com/subject/rdhywftx.html