(1)mysql 锁、索引、事务

这里放一张 mysql 的架构图

(1)mysql 锁、索引、事务_第1张图片
image.png

一个大佬博客地址 http://hedengcheng.com/

在开发中遇到问题场景描述

看到日志

SQL []; Deadlock found when trying to get lock; 
try restarting transaction; nested exception is 
com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: 
Deadlock found when trying to get lock; try restarting transaction

哪个语句造成的?(promotion_id 和 spu_id 是单独建立的索引)

 update activity_spu
        set total_purchased_qty = total_purchased_qty +?
        where promotion_id = ?
        and spu_id = ?
        and is_delete = 0;

为什么会出现死锁?展开的一些知识的调研,下面内容都比较零散,希望,日后希望 mysql 的知识成为全面的时候在做归纳。

两阶段锁(可能出现死锁)

首先 事务 A 拿到锁,第一个 update 和第二个 update 分别再拿到锁,
这时候在事务提交之前是不会释放锁,只有在事务提交后缩才会分别被释放,事务 B 也就是说一直在等待 id=1的锁.


(1)mysql 锁、索引、事务_第2张图片
image.png

在 InnoDB 事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,而是要等到事务结束时才释放。这个就是两阶段锁协议
如果你的事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁尽量往后放。
但是这样子的话可能就出现死锁的问题了


(1)mysql 锁、索引、事务_第3张图片
image.png

话说回来这样的字死锁很好解决,调整一下 update 顺序就可以解决,但是更多的出现的问题是这样子的。

根据主键索引更新语句的过程

 update activity_spu
        set total_purchased_qty = total_purchased_qty +?
        where promotion_id = ?
        and spu_id = ?
        and is_delete = 0;

这里肯定会加上行级锁。
行级锁并不是直接锁记录,而是锁索引,如果一条SQL语句用到了主键索引,mysql会锁住主键索引;
如果一条语句操作了非主键索引,mysql会先锁住非主键索引,再锁定主键索引。
这个update语句会执行以下步骤:

1、由于用到了非主键索引,首先需要获取普通索引上的行级锁

2、紧接着根据主键进行更新,所以需要获取主键上的行级锁;

3、更新完毕后,提交,并释放所有锁。

InnoDB 的索引模型

InnoDB 使用了 B+ 树索引模型,所以数据都是存储在 B+ 树中的
索引类型分为主键索引和非主键索引

主键索引的叶子节点存的是整行数据。在 InnoDB 里,主键索引也被称为聚簇索引(clustered index)

非主键索引的叶子节点内容是主键的值。在 InnoDB 里,非主键索引也被称为二级索引(secondary index)。

(1)mysql 锁、索引、事务_第4张图片
image.png

基于主键索引和普通索引的查询有什么区别?

  • 如果语句是 select * from T where ID=500,即主键查询方式,则只需要搜索 ID 这棵 B+树;
  • 如果语句是 select * from T where k=5,即普通索引查询方式,则需要先搜索 k 索引树,得到 ID 的值为 500,再到 ID 索引树搜索一次。这个过程称为回表。

也就是说,基于非主键索引的查询需要多扫描一棵索引树。因此,我们在应用中应该尽量使用主键查询。

索引是如何维护的

叶节点有在删除的时候合并,在增加的时候会分裂

要求建表语一定要有自增主键?

效率角度:自增主键的插入数据模式,正符合了我们前面提到的递增插入的场景。每次插入一条新记录,都是追加操作,都不涉及到挪动其他记录,也不会触发叶子节点的分裂。

空间角度:由于每个非主键索引的叶子节点上都是主键的值。如果用身份证号做主键,那么每个二级索引的叶子节点占用约 20 个字节,而如果用整型做主键,则只要 4 个字节,如果是长整型(bigint)则是 8 个字节。

你可能感兴趣的:((1)mysql 锁、索引、事务)