MySQL学习笔记(五)InnoDB事务与锁

什么是事务

数据库事务,事务就是【一组原子性的SQL】,独立不可分割的工作单元,要保证这个事务里的SQL 要么全部成功要么全部失败。

四大特性

ACID

Atomicity 原子性(回滚日志 undolog) 

Durability 持久性 (重做日志 redolog)

isolation 隔离性

consistency 一致性

事务并发存在的问题

脏读

幻读

不可重复读

不可重复读与幻读有什么区别?

不可重复读:重点是在于修改,在一个事务中,同样的条件,第一 次读取的数据与第二次【数据不一样】(因为中间有其他事务对这 个数据进行了修改)

幻读:重点在于新增,在一个事务中,同样的条件(范围),第一 次读取和第二读取【记录条数不一样】(因为中间有其他事务在这个范围里插入、删除了的数据)

数据库隔离性

Read UnCommited 读取未提交

没有解决任何问题,存在脏读,因为他就是读取最新的数据。

Read Commited 读取已提交

只读取已提交的的事务,可以解决脏读问题。

Repeatable Read

RR级别解决了脏读、不可重复读、幻读的问题。在第一次读取时,他会生成一次ReadView,之后每次读取都只会读取这个 ReadView.

Serializable 串行执行

串行排队读取,性能最低。

MVCC 非锁定一致性读取

非锁定一致性查询将看到由以下事务所做的更改在该时间点 前提交,并且未进行任何更改稍后或未提交的事务。

官网地址:https://dev.mysql.com/doc/refman/8.0/en/innodb-con sistent-read.html

如何实现?

每个事务都有一个事务ID,并且是递增,我们后续MVCC的原理都是基于它去完成。

效果:建立一个快照,同一个事务无论查询多少次都是相同的数据。

一个事务能看见的版本:

1. 第一次查询之前已经提交的版本

2. 本事务的修改

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

1. 在本事务第一次查询之后创建的事务(事务ID比我大)

2. 活跃中的(未提交)的时候的修改。

然后InnoDB会在每行的后面都添加 3个隐藏字段。

DB_TRX_ID:表示最近一次对本记录做修改/插入的事务ID。

DB_ROLL_PTR:回滚指针,指向当前记录行的undo log信息

DB_ROW_ID:随着新行插入而单调递增的行ID。

ReadView(读视图) 结构

什么是ReadView,事务进行快照读、当前读操作的 时候,产生一个读视图,在事务执行读的一刻,生成数据库系统当前的一个快照,记录并且维护系统当前活跃事务ID。 (当每个事务开启时,都会被分配一个ID, 这个ID是递增的,所以最新的事务,ID值越大)

这里解释一下,什么是快照读: 普通读的执行方式是生成 ReadView,直接利用 MVCC 机制来进行读取,并不会对记录进行加锁

当前读对读取的记录加锁, 阻塞其他事务同时改动相同记录,避免出现安全问题。

快照读:MVCC Read View。

当前读:对记录加锁,阻塞其他事务同时修改相同的记录,避免安全的问题。

Read View 判断规则

数据行的隐藏列 trx_id = creator_trx_id,在本事务修改的我是可见的。

trx_id = min_trx_id(未提交的事务最小ID),说明这个版本在ReadView 视图创建之前已经创建,但是还未提交,所以不能够读取。

trx_id在我们的活跃的m_ids数组里, trx_id < min_trx_id, 说明这个版本在ReadView 开启之前事务已经提交了,可以访问。   

trx_id >= max_trx_id,说明这个版本在我ReadView 开启之后才创建的,不管你是否提交我都无法访问。

MVCC 总结:

MVCC 是适合用于处查询的时候使用,能提供很高的性能,我们的事务不仅仅是只有读,我们还有写情况,为了保证数据不丢失,我们需要拿到最新的数据进行更改。

数据库并发场景有三种,分别为:

1、读读: 不存在任何问题,也不需要并发控制

2、读写、写读: 有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读、幻读、不可重复读。

3、写写: 有线程安全问题,可能存在更新丢失问题。

MVCC是一种用来解决读写冲突的无锁并发控制,也就是为事务分配单项增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联.读操作只读该事务开始前的数据库的快照,所以MVCC可 以为数据库解决一下问题:

1、在并发读写数据库时,可以做到在读操作时不用阻塞写操作,写 操作也不用阻塞读操作,提高了数据库并发读写的性能

2、解决脏读、幻读、不可重复读等事务隔离问题,但是不能解决更新丢失问题。

LBCC 锁定读取

如果查询数据,然后在其他的事务可能会对你查询的数据进行更改,(SELECT) 常规语句没有给出足够的保护,其他事务可以更新或删除刚刚查询的相同行。

粒度:表锁、行锁

类型:共享(读)、排它(写)、意向共享、意向排他

用户:乐观锁、悲观锁

算法:记录、临检、间隙锁

锁类型

共享锁

我们发现加上了共享锁之后,其他事务是可以加共享锁,意味 着共享锁之间不互斥,但是其他事务不可以对加了共享锁的数据进 行加排他锁,意味着共享锁与排他锁互斥。

排他锁

我们发现一个数据加上了排他锁之后,其他数据对其进行加排他锁是不可行的,意味着排他锁与排他锁互斥。如果我们再对这个 数据加上共享锁也是不行的,因为排他锁与其他锁(排它锁、共享 锁)都互斥。

锁算法

记录锁

阻止任何其他事务插入、更新或删除值为 的行。

SELECT id FROM t WHERE id = 10 FOR UPDATE; 用主键加锁

间隙锁

间隙锁是索引记录之间间隙上的锁,或锁在第一个索引记录之前或之后的间隙上。例如,阻止插入其他事务的insert into;间 隙锁是索引记录之间间隙上的锁,或锁在第一个索引记录之前或之 后的间隙上。例如,阻止插入其他事务的 into 列的值。

临检锁

记录锁+临检锁的组合 InnoDB执行行级锁定的方式是,当它搜索或扫描表索引时,它会对遇到的索引记录设置共享或独占锁。因此,行级锁实际上是索引记录锁。索引记录上的临检锁锁定也会影响该索引记录之前的“间 隙”。也就是说,临检锁是索引记录锁加上索引记录之前间隙上的间隙锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值