网站推广方案策划案例,网站建设岗位有哪些,百度网站的总结,广州建设工程领域平台登录其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录
其他系列文章导航
文章目录
前言
一、事务
1.1 含义
1.2 ACID
二、锁机制
2.1 锁分类
2.2 隔离级别
三、MVCC
3.1 介绍
3.2 隔离级别
3.3 原理
四、总结 前… 其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录
其他系列文章导航
文章目录
前言
一、事务
1.1 含义
1.2 ACID
二、锁机制
2.1 锁分类
2.2 隔离级别
三、MVCC
3.1 介绍
3.2 隔离级别
3.3 原理
四、总结 前言
转眼又一年~~2023马上就要到尾声了在最后的几天中我想给大家分享一下 MySQL 的一些小知识。 一、事务
1.1 含义
通俗理解在我的理解下事务可以使 一组操作要么全部成功要么全部失败。事务其目的是为了下保证数据最终的一致性。
举个例子举个例子我给你发支付宝转了666块红包。那自然我的支付宝余额会扣减666块你的支付宝余额会增加666块。 1.2 ACID
原子性 (Atomicity)一致性 (Consistency)隔离性 (lsolation)持久性 (Durability)
原子性指的是:当前事务的操作要么同时成功要么同时失败。原子性由undo log日志来保证因为undo log记载着数据修改前的信息。 比如我们要 insert 一条数据了那undo log 会记录的一条对应的 delete 日志。我们要 update 一条记录时那undo log会记录之前的 旧值 的update记录。 如果执行事务过程中出现异常的情况那执行 [回滚]。InnoDB引擎就是利用undo log记录下的数据来将数据 恢复 到事务开始之前。 隔离性指的是:在事务并发执行时他们内部的操作不能互相干扰。 如果多个事务可以在同一时刻操作同一份数据那么就会可能会产生脏读、重复读、幻读的问题。 于是事务与事务之间需要存在 一定 的隔离。在InnoDB引擎中定义了四种隔离级别供我们使用: read uncommit(读未提交)read commit (读已提交)repeatable read(可重复复读)serializable (串行) 不同的隔离级别对事务之间的隔离性是不一样的 (级别越高事务隔离性越好但性能就越低) 而隔离性是由MySQL的各种锁来实现的只是它屏蔽了加锁的细节。 持久性指的就是:一旦提交了事务它对数据库的改变就应该是永久性的。说白了就是会将数据持久化在硬盘上。 而持久性由 redo log 日志来保证当我们要修改数据时MySQL是先把这条记录所在的页找到然后把该页加载到内存中将对应记录进行修改。 为了防止内存修改完了MySQL就挂掉了(如果内存改完直接挂掉那这次的修改相当于就丢失了)。 MySQL引入了 redo log内存写完了然后会写一份 redo log这份 redo log 记载着这次在某个页上做了什么修改。 即便 MySQL 在中途挂了我们还可以根据 redo log来对数据进行恢复。 redo log 是顺序写的写入速度很快。并且它记录的是物理修改 (xxxx页做了xxx修改)文件的体积很小恢复速度也很快。 一致性指的就是:我们使用事务的目的 而[隔离性][原子性][持久性]均是为了保障 [一致性] 的手段保证一致性需要由应用程序代码来保证。 比如如果事务在发生的过程中出现了异常情况此时你就得回滚事务而不是强行提交事务来导致数据不一致。 二、锁机制
2.1 锁分类 在InnoDB引擎下按锁的粒度分类可以简单分为
行锁表锁
行锁实际上是作用在索引之上的。
当我们的 SQL 命中了索引那锁住的就是命中条件内的索引节点(这种就是行锁)如果没有命中索引那我们锁的就是整个索引树 (表锁)。
简单来说就是:锁住的是整棵树还是某几个节点完全取决于 SQL 条件是否有命中到对应的索引节点。
而行锁又可以简单分为
读锁 (共享锁、S锁)写锁 (排它锁、X锁)
读写锁区别
读锁是共享的多个事务可以同时读取同一个资源但不允许其他事务修改。写锁是排他的写锁会阻塞其他的写锁和读锁。 2.2 隔离级别
再回到隔离级别上吧以例子来说明。
首先来说下read uncommit(读未提交)比如说: A向B转账A执行了转账语句但A还没有提交事务B读取数据发现自己账户钱变多了! B跟A说我已经收到钱了。A回滚事务[rollback]等B再查看账户的钱时发现钱并没有多。
简单的定义就是:事务B读取到了事务A还没提交的数据这种用专业术语来说叫做[脏读]。
对于锁的维度而言其实就是在read uncommit隔离级别下读不会加任何锁而写会加排他锁。读什么锁都不加这就让排他锁无法排它了。
而我们又知道对于更新操作而言InnoDB是肯定会加写锁的 (数据库是不可能允许在同一时间更新同一条记录的)。而读操作如果不加任何锁那就会造成上面的脏读。
脏读在生产环境下肯定是无法接受的,那如果读加锁的话那意味着:当更新数据的时就没办法读取了这会极大地降低数据库性能。 三、MVCC
3.1 介绍
在MySQL InnoDB引擎层面又有新的解决方案 (解决加锁后读写性能问题)叫做MVCC(Multi-Version Concurrency Control)多版本并发控制。
在MVCC下就可以做到读写不阻塞且避免了类似脏读这样的问题。那MVCC是怎么做的呢?
MVCC通过生成数据快照 (Snapshot)并用这个快照来提供一定级别 (语句级或事务级)的一致性读取。
3.2 隔离级别
回到事务隔离级别下针对于 read commit (读已提交) 隔离级别它生成的就是语句级快照而针对于repeatable read(可重复读)它生成的就是事务级的快照。
前面提到过read uncommit隔离级别下会产生脏读而read commit (读已提交)隔离级别解决了脏读。
思想其实很简单:在读取的时候生成一个版本号等到其他事务commit了之后才会读取最新已commit的版本号数据。 比如说: 事务A读取了记录(生成版本号)事务B修改了记录(此时加了写锁)事务A再读取的时候是依据最新的版本号来读取的(当事务B执行commit了之后会生成一个新的版本号)如果事务B还没有commit那事务A读取的还是之前版本号的数据。 通过[版本]的概念这样就解决了脏读的问题而通过 版本又可以对应快照的数据。
read commit (读已提交) 解决了脏读但也会有其他并发的问题。 [不可重复读]:一个事务读取到另外一个事务已经提交的数据也就是说一个事务可以看到其他事务所做的修改。 不可重复读的例子: A查询数据库得到数据B去修改数据库的数据导致A多次查询数据库的结果都不一样[危害: A每次查询的结果都是受B的影响的]。 了解MVCC基础之后就很容易想到repeatable read (可重复复读)隔离级别是怎么避免不可重复读的问题了 (前面也提到了)。
repeatable read (可重复复读)隔离级别是 事务级别]的快照!每次读取的都是厂当前事务的版本]即使当前数据被其他事务修改了(commit)也只会读取当前事务版本的数据。
在InnoDB引擎下的的repeatable read(可重复复读)隔离级别下在MVCC下快照读已经解决了幻读的问题 (因为它是读历史版本的数据)。
而如果是当前读 (比如 select * from table for update),则需要配合间隙锁来解决幻读的问题。
剩下的就是serializable (串行)隔离级别了它的最高的隔离级别相当于不允许事务的并发事务与事务之间执行是串行的它的效率最低但同时也是最安全的。
3.3 原理
MVCC的主要是通过read view和undo log来实现的。
undo log前面也提到了它会记录修改数据之前的信息事务中的原子性就是通过undo log来实现的。所以有undo log可以帮我们找到 版本]的数据。
而read view 实际上就是在查询时InnoDB会生成一个read viewread view 有几个重要的字段看下去就懂了。
trx ids (尚未提交commit的事务版本号集合)low limit id (下一次要生成的事务ID值)low limit id (尚未提交版本号的事务ID最小值)creator_trx_id (当前的事务版本号)
在每行数据有两列隐藏的字段分别是DB TRX ID (记录着当前ID) 以及DB ROLL PTR (指向上一个版本数据在undolog 里的位置指针)。 铺垫到这了很容易就发现MVCC其实就是靠[比对版本来实现读写不阻塞而版本的数据存在于undo log中。 而针对于不同的隔离级别 (read commit和repeatable read) 无非就是read commit隔离级别下每次都获取一个新的1ead viewrepeatable read隔离级别则每次事务只获取一个read view 四、总结
事务、锁机制和 MVCC 是数据库管理系统中的三个核心概念它们协同工作以确保数据的完整性和并发性。
在 MySQL 中事务提供了一种方法来管理数据库操作的逻辑边界锁机制用于控制对数据的并发访问而 MVCC 则通过允许多个事务同时读取数据来提高并发性能。
了解和正确使用这些概念对于数据库管理员和开发人员来说至关重要以确保数据库应用的性能和可靠性。