MySQL之事务 索引 锁_(1)mysql 锁、索引、事务

这里放一张 mysql 的架构图

1b4312325440

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的锁.

1b4312325440

image.png

在 InnoDB 事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,而是要等到事务结束时才释放。这个就是两阶段锁协议

如果你的事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁尽量往后放。

但是这样子的话可能就出现死锁的问题了

1b4312325440

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)。

1b4312325440

image.png

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

如果语句是 select * from T where ID=500,即主键查询方式,则只需要搜索 ID 这棵 B+树;

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

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

索引是如何维护的

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

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

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值