MySQL的事务与锁

目录

什么是事务

事务的特性

事务并发产生的问题

事务隔离级别

事务隔离级别的实现

MVCC

Read View(一致性视图)

锁(LBCC)

锁的算法


什么是事务

        事务就是一条sql语句或者多条sql语句所组成的逻辑执行单元,要么全部执行成功要么全部执行失败,目的是保证数据的一致性

并不是所有的存储引擎都支持事务,InnoDB,NDB是支持事务的。

事务的特性

        在Mysql中事务的四大特性主要包含:原子性(Atomicity)一致性(Consistency)隔离性(lsolation)持久性(Durability),简称为ACID

  • 原子性:指事务的原子性操作,即对数据的修改要么全部执行成功要么全部执行失败。是基于undo日志来实现的。
  • 一致性:指执行事务前后要状态要一致,可以理解成数据的一致性。
  • 隔离性:隔离性侧重指事务之间相互隔离,不受影响,这个与事务设置的隔离级别有密切的关系。
  • 持久性:指在一个事务提交后,这个事务的状态会被持久化到数据库中。是基于redo日志来实现的

原子性、隔离性、持久性都是为了保障一致性而存在的,一致性也是最终的目的。

事务并发产生的问题

脏读:一事务对数据进行了增删改,但未提交,另一事务可以读取到未提交的数据。如果第一个事务这时候回滚了,那么第二个事务就读到了脏数据。

不可重复读:一个事务中发生了两次读操作,第一次读操作和第二次操作之间,另外—个事务对数据进行了修改,这时候两次读取的数据是不一致的。(update/delete)

幻读:第一个事务对一定范围的数据进行批量修改,第二个事务在这个范围增加一条数据,这时候第一个事务就会丢失对新增数据的修改。(insert)

事务隔离级别

        在Mysql中事务的隔离级别分为四大等级,读未提交(READ UNCOMMITTED)、读提交 (READ COMMITTED)、可重复读 (REPEATABLE READ)、串行化 (SERIALIZABLE)。MySql默认的隔离级别是可重复读。

读未提交:可以读取另一个事务没有提交的数据。没有解决任何并发问题

读已提交:读取最新数据,可以读取另一个事务提交了的数据。解决了脏读问题。

可重复读:在同一个事务中多次读取同样的数据结果是一样的。解决了脏读和不可重复读,没有解决幻读。

串行化:最高的隔离级别,通过强制事务的串行执行。没有并发性可言,性能差。

InnoDB存储引擎在RR级别就解决了幻读问题。

事务隔离级别的实现

Read Uncommited :不加锁

Serializable:所有的select语句都会被隐式的转化为select ... in share mode,会和update.delete互斥。

RR 与 RC

RRRC
普通的select(快照读)MVCCMVCC

加锁的select和更新(当前读)

select ... in share mode

select ... for updateinsert
update

delete

Record Lock

Gap Lock
Next-key Lock

Record Lock

RC和RR的主要区别:

  • RR的间隙锁会导致锁定范围的扩大。
  • 条件列未使用到索引,RR锁表,RC锁行。
  • RC的“半一致性”(semi-consistent)读可以增加update操作的并发性。

MVCC

多版本并发控制,也叫快照读,非阻塞读。 

lnnodb为每行记录都实现了三个隐藏字段

  • DB_ROW_ID  6字节:行标识
  • DB_TRX_ID  6字节:插入或更新行的最后一个事务的事务ID,自动递增(创建版本号)
  • DB_ROLL_PTR  7字节:回滚指针(删除版本号)

快照读效果:建立了一个快照,同一个事务无论查多少次都是相同的数据。
一个事务能看到的数据版本:

  • 第一次查询之前已经提交的事务的修改
  • 本事务的修改

一个事务不能看见的数据版本:

  • 在本事务第一次查询之后创建的事务(事务ID比我的事务ID大)
  • 活跃的(未提交的)事务的修改

MVCC基于Read View和undo log来实现

Read View(一致性视图)

RR的 Read View是事务第一次查询的时候建立的。

RC的 Read View是事务每次查询的时候建立的。

m_ids{}里是活跃的事务id,也就是还没提交的事务

min_trx_id是m_ids里子最小的事务id,也就是未提交事务的最小id,所以小于它的一定都提交了

max_trx_id是m_ids里子最大的事务id+1(代表即将分配的id),所以大于它的是生成ReadView之后才开启的事务,所以是读不到了。

creator_trx_id是生成ReadView事务的id,也就是当前事务的id.

 Read View判断规则

  1. 从数据的最早版本开始判断(undo log)
  2. 数据版本的trx_id = creator_trx_id,本事务修改,可以访问
  3. 数据版本的trx_id <= min_trx_id(未提交事务的最小ID),说明这个版本在生成ReadView已经提交,可以访问
  4. 数据版本的trx_id >= max_trx_id(下一个事务ID),这个版本是生成ReadView之后才开启的事务建立的,不能访问
  5. 数据版本的trx_id在min_trx_id和max_trx_id之间,看看是否在m_ids中。如果在,不可见。如果不在,可见。
  6. 如果当前版本不可见,就找undo log链中的下一个版本。

锁(LBCC)

锁的本质是什么:锁的本质是锁索引,如果非索引的字段加锁会导致锁表。

锁的粒度

MyISAM和InnoDB分别支持什么粒度的锁?

InnoDB支持行锁和表锁,而MyISAM只支持表锁。

表锁与行锁的区别:

  • 锁定粒度∶ 表锁 > 行锁
  • 加锁效率:表锁 > 行锁
  • 冲突概率:表锁 > 行锁
  • 并发性能:表锁 < 行锁

InnoDB锁类型

  • 共享锁(行锁):Shared Locks
  • 排它锁(行锁):Exclusive Locks
  • 意向共享锁(表锁):Intention Shared Locks
  • 意向排它锁(表锁):Intention Exclusive Locks

.共享锁

        又称为读锁,简称S锁,顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改;

加锁释锁方式:

select * from student where id=1 LOCK IN SHARE MODE;

锁会在事务提交或者回滚时释放,或者当连接断开也会释放锁。

拿不到锁的事务会等待,默认等待50s

排他锁

        又称为写锁,简称X锁,排他锁不能与其他锁并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的锁(共享锁、排他锁),只有该获取了排他锁的事务是可以对数据行进行读取和修改。

加锁释锁方式:

自动: delete / update / insert 默认加上X锁;
手动: select* from student where id=1 FOR UPDATE;

意向锁

意向锁是由数据引擎自己维护的,用户无法手动操作意向锁。

在我们加行锁的时候,存储引擎会帮们加上表锁。(这大大提高了加表锁的效率)

意向共享锁(Intention shared Lock,简称IS锁)表示事务准备给数据行加入共享锁,也就是说一个数据行加共享锁前必须先取得该表的IS锁。

意向排他锁(Intention Exclusive Lock,简称IX锁)表示事务准备给数据行加入排他锁,说明事务在一个数据行加排他锁前必须先取得该表的IX锁。

死锁的避免

  • 顺序访问数据排序
  • 申请足够级别的锁
  • 避免没有where条件的操作
  • 大事务分解成小事务
  • 使用等值查询而不是范围查询

锁的算法

记录锁(Record):在指定的一行数据加记录锁

间隙锁(Gap):在范围加锁时,范围内没有数据,会给这个间隙加间隙锁。间隙锁的最大作用就是阻塞插入,可以解决幻读问题。

临建锁(Next-key):记录锁+间隙锁。范围加锁时,范围内有数据,会加临建锁,

记录锁

 间隙锁

 临建锁

select * from t2 where id>1 and id <7 for update;

锁住的范围是(1, 7]

select * from t2 where id>1 and id <=7 for update;

锁住的范围是(1, 10]

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

w7486

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值