如何做好网站推广方法,视频剪辑培训机构,没有办公地点怎么注册自己的公司,建建建设网站首页目录
1. 整体学习思维导图
2. 什么是事务
2.1 事务的概念
2.2 事务的属性(ACID)
2.3 事务出现的原因
2.4 查看存储引擎对事务的支持
3. 事务的使用
3.1 事务的提交方式
3.1.1 手动提交
3.1.2 自动提交
结论#xff1a;
3.2 事务的隔离级别
3.2.1 理解隔离
3.2.2…目录
1. 整体学习思维导图
2. 什么是事务
2.1 事务的概念
2.2 事务的属性(ACID)
2.3 事务出现的原因
2.4 查看存储引擎对事务的支持
3. 事务的使用
3.1 事务的提交方式
3.1.1 手动提交
3.1.2 自动提交
结论
3.2 事务的隔离级别
3.2.1 理解隔离
3.2.2 设置隔离级别
3.2.3 隔离级别
读未提交(Read Uncommitted)
读提交(Read Committed)
可重复读(Repeatable Read)
串行化(Serializable)
总结
4. 隔离性和隔离级别的理解
4.1 数据库的并发场景
4.2 读-写场景并发(MVCC)理解
4.2.1 事务ID
4.2.2 三个隐藏记录字段
4.2.3 undo日志
模拟MVCC:
探讨
4.3 当前读和快照读
4.3.1 Read View
4.4 RR与RC的区别 1. 整体学习思维导图 2. 什么是事务
2.1 事务的概念
事务是从应用层面上来看待的比如在一个同学退学了我们需要在学校的教务系统的数据库中将该同学的信息选课成绩都要删除掉这需要一系列的SQL语句而我们就把这个处理的DML语句集合称作为一个事务
2.2 事务的属性(ACID) 原子性(Atomicity)一个事务的所有操作要么全部执行要么全部未执行不能出现中间的状态。就拿前面的比方同学退学我们的退学事务不能只说删除同学的信息但不去删除选课和成绩如果一个事务在执行过程中发生错误那么该事务就会回滚(rollback)到没执行的状态 一致性(Consistency)事务的执行结果是可以预期的比如A向B转账50那么A的账户会减少50B的账户会增加50A向B转账的过程就是一个事务而这个事务的结果是可以预期的就称作为一致性。MySQL对于一致性并没有做过多的设计MySQL是通过AID来保证C一致性的简单说AID是因C是果。 隔离性(Isolation)每个事务执行的期间是隔离的数据库允许多个并发的事务对数据进行读写操作隔离性可以防止多个事务在读写数据交叉导致数据的不一致。 隔离性的级别(根据隔离影响划分) 读未提交(Read UnCommitted) 读提交(Read Committed) 可重复读(repeatable read) 串行化(Serializable) 持久性(Durability)事务处理结束之后对于数据的修改是永久性的即使系统故障也不会丢失。
查看事务隔离级别
查看全局
mysql select global.tx_isolation;
-----------------------
| global.tx_isolation |
-----------------------
| REPEATABLE-READ |
-----------------------
1 row in set, 1 warning (0.00 sec) 查看当前会话
mysql select session.tx_isolation;
------------------------
| session.tx_isolation |
------------------------
| REPEATABLE-READ |
------------------------
1 row in set, 1 warning (0.00 sec)
查看默认
mysql select tx_isolation;
-----------------
| tx_isolation |
-----------------
| REPEATABLE-READ |
-----------------
1 row in set, 1 warning (0.00 sec)
2.3 事务出现的原因
事务的本质是一系列的DML语句但是我们在应用层编写时不可能时常去注意细节我们可以用面向对象的思想来解释而事务就相当于一个对象它将DML语句描述后组织起来。
我们还将MySQL中的一条信息称作为一条记录。
2.4 查看存储引擎对事务的支持
mysql show engines \G;
*************************** 1. row ***************************Engine: InnoDBSupport: DEFAULTComment: Supports transactions, row-level locking, and foreign keys
Transactions: YES -- 对事务支持XA: YESSavepoints: YES
*************************** 2. row ***************************Engine: MRG_MYISAMSupport: YESComment: Collection of identical MyISAM tables
Transactions: NO -- 对事务不支持XA: NOSavepoints: NO3. 事务的使用
3.1 事务的提交方式 手动提交 自动提交
3.1.1 手动提交
我们先创建一个测试表
create table if not exists T_TB( id int primary key comment编号, name varchar(20) default, age tinyint
);
手动提交和自动提交互不影响下面是手动提交的开启/结束
begin/start transaction
commit;
手动创建回滚点
mysql savepoint save1; Query OK, 0 rows affected (0.00 sec)-- 创建一个保存点save1
mysql rollback to save1; -- 回滚到保存点save1 如果手动开始的事务没有提交程序崩溃后会自动回滚手动开始事务提交后即使程序崩溃也会持久化保存 自动提交的开启是否不影响手动提交
3.1.2 自动提交
查看自动提交是否开启OFF(没有开启)/ON(开启)
mysql show variables likeautocommit;
----------------------
| Variable_name | Value |
----------------------
| autocommit | ON |
----------------------
1 row in set (0.00 sec)
自动提交开启后我们正常进行一条条CURD操作都是一个个事务即使程序异常崩溃也会持久化保存如果关闭自动提交进行CURD操作我们程序异常崩溃后会回滚
所以操作能否对数据进行持久化的影响取决于是否提交了
结论 3.2 事务的隔离级别
3.2.1 理解隔离 隔离性数据库中为了保证事务执行过程中尽量不受干扰就有了一个重要特征隔离性。 隔离级别数据库中允许事务受不同程度的干扰就有了一种重要特征隔离级别 。
3.2.2 设置隔离级别
我们前面讲了如何查看隔离级别这边我们来看如何设置隔离级别
--设置
-- 设置当前会话 or 全局隔离级别语法
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED(读未提交) | READ
COMMITTED(读提交) | REPEATABLE READ(可重复读) | SERIALIZABLE(串行化)} 当前会话只作用于这一次会话一旦退出就消失 全局更新完全局隔离级别需要重启MySQL才会生效
3.2.3 隔离级别
读未提交(Read Uncommitted)
在该隔离级别下两个事务并发读写数据其中一方事务进行读操作另一方事务进行写操作读操作的事务可以实时看到写操作事务对数据的修改(即使写操作事务并没有进行提交)我们将读操作事务读取到的数据称作为脏读(因为写操作事务没有提交cmmit,我们是不知道读取的数据是否会回滚rollback) 读提交(Read Committed)
在该隔离级别下两个事务并发读写数据时任何一方想看到另外一方的修改需要等对方提交才可以但是它会带来一个问题--不可重复度不可重复读是指原本我们的数据内容只有三条记录我们第一次读取也是三条与此同时另一个事务进行了insert并且结束了事务我们这边的事务又进行了一次查询发现表中的数据改变成了四条与前面的三条不相符我们将这种现象称作为不可重复读 可重复读(Repeatable Read)
在该隔离级别下两个事务并发读写数据时任何一方在事务过程中都不会影响到另一个事务即使第一个事务已经结束DML操作但是第二个事务是无法看到进过操作后的表。只有双方都结束并且commit才可以看到对方的修改。 多次查看发现终端A在对应事务中insert的数据在终端B的事务周期中也没有什么影响也符合可重复的特点。但是一般的数据库在可重复读情况的时候无法屏蔽其他事务insert的数据(为什么因为隔离性实现是对数据加锁完成的而insert待插入的数据因为并不存在那么一般加锁无法屏蔽这类问题),会造成虽然大部分内容是可重复读的但是insert的数据在可重复读情况被读取出来导致多次查找时会多查找出来新的记录就如同产生了幻觉。这种现象叫做幻读(phantom read)。
串行化(Serializable)
在该隔离级别下两个事务并发读写数据时两个事务就需要进行排队执行只有在对方提交完成后另一方才可以进行相应的操作(读取数据不受影响)。 我们可以看见更新SQL语句卡住了。 当我们右边事务提交后卡住的SQL执行成功 总结 隔离级别越高安全性越好但是数据库的并发性能就会降低我们需要根据需求找到一个平衡点。 不可重复读重点在于修改和删除 幻读的重点在于新增的数据
4. 隔离性和隔离级别的理解
4.1 数据库的并发场景 读-读不存在问题 读-写存在问题可能会出现(脏读/幻读/不可重复读) 写-写存在问题
4.2 读-写场景并发(MVCC)理解
我们先来理解数据库中出现并发场景最多的读-写场景。
多版本并发控制(MVCC)是一种解决读-写问题的无锁并发控制。
在理解MVCC之前我们需要来学习一些前置知识点 三个隐藏记录字段 undo日志 Read View
4.2.1 事务ID
每个事务都要有自己的ID,ID决定他们到来的先后顺序。
MySQL可能有时并发的处理多个事务事务也就有了自己的生命周期那么我们就需要对事务进行先描述在组织通过一个对象或者结构体将事务管理起来
4.2.2 三个隐藏记录字段 DB_TRX_ID称作为最近修改事务ID记录创建这条记录/最后一次修改(修改/插入)该记录的事务ID 。 DB_ROLL_PTR: 称作为回滚指针用于指向该条记录的上个版本。 DB_ROW_ID:隐含的自增ID隐藏主键如果数据表没有主键 InnoDB 会自动以DB_ROW_ID 产生一个聚簇索引
补充还有一个flag字段用于表示该条记录是否删除比如说1表示删除0表示存在。记录的更新和删除不一定是真的删除了
-- 我们创建一个测试表只有姓名和年龄
mysql create table if not exists T_MVCC(- name varchar(15),- age int unsigned- );
Query OK, 0 rows affected (0.02 sec)mysql insert into T_MVCC values(张三, 18);
Query OK, 1 row affected (0.00 sec)mysql select * from T_MVCC limit 1;
--------------
| name | age |
--------------
| 张三 | 18 |
--------------
1 row in set (0.00 sec)
我们将隐藏的字段也添加上DB_TRX_ID默认null,DB_ROLL_PTR默认null,DB_ROW_ID默认1。 name age DB_TRX_ID DB_ROLL_PTR DB_ROW_ID 张三 18 null null 1
4.2.3 undo日志
我们需要知道MySQL数据库在我们对数据进行的操作短时内都是在内存中执行的根据算法过一定的时间或者满足一定的条件数据才会被从内存向磁盘上写入
而undo log就是存放在内存缓冲区用于日志信息
模拟MVCC: 前提条件我们需要将张三的age修改为20(update)。 在事务ID: 1修改前给该条记录加上行锁然后拷贝一份旧版本到undo log中等待事务1提交后解锁。修改后的事务ID: 1中的PTR指向上个版本这样可以方便进行回滚操作
而我们可以将undo log中的版本称作为一个个快照
探讨 对于删除delete,我们前面介绍过flag所以删除也可以形成一个版本进行存放在执行删除操作时内部存放的是与之相反的添加的SQL,一旦回滚就执行该SQL。 对于插入insertinsert插入的是之前版本没有的数据按前面来看insert是无法形成一个旧版本的但是为了回滚操作insert的数据也要被存放到undo log中,只有当commit后insert存到的数据才会被清空 对于select呢我们什么时候读当前最新的数据(当前读)还是去读取旧数据(快照读)呢我们下面来详细看看
4.3 当前读和快照读
控制当前读还是快照读取决于隔离级别我们虽然说事务的属性是原子性的但是在MySQL处理事务的过程中也是存在先后的顺序而这个顺序将决定读取数据的版本和范围
可以简单说当前读还是快照读一个事务该读取那些版本的数据也就是隔离级别实现的本质。
4.3.1 Read View Read View就是事务进行 快照读 操作的时候生产的 读视图 (Read View)在该事务执行的快照读的那一刻会生成数据库系统当前的一个快照记录并维护系统当前活跃事务的ID(当每个事务开启时都会被分配一个ID, 这个ID是递增的所以最新的事务ID值越大) Read View 在 MySQL 源码中,就是一个类本质是用来进行可见性判断的。 我们创建一个事务的时候不会创建Read View, 只有当我们某个事务执行快照读(select)的时候对该记录创建一个 Read View 读视图把它比作条件,用来判断当前事务能够看到哪个版本的数据既可能是当前最新的数据也有可能是该行记录的 undo log 里面的某个版本的数据。
Read View类的主要成员变量
m_ids; // 相当于一张列表记录当前活跃的事务的ID
up_limit_id; // 用于记录m_ids表中最小的事务ID
low_limit_id; // 用于记录所有事务中(包括已经commit的)最大的ID值1
creator_trx_id //创建该ReadView的事务ID 通过上图
在m_ids表中的ID存在 1 2 3
up_limit_id1
low_limit_id: 5
creator_trx_id: 2
事务4修改操作后id是不存在于m_ids,并且也不大于low_limit_id快照读是可见事务4的版本。
4.4 RR与RC的区别 select * from user lock in share mode ,以加共享锁方式进行读取对应的就是当前读该条语句可以读到最新的版本。
RR: 一个Read View用到底 RC: 每次快照读都会更新Read View
比方说我们现在存在着事务A,事务B: 我们先以RR做举例事务B在快照读时生成的Read View中的m_ids中存放着事务A的ID所以事务B是看不见事务A的修改版本即使提交后由于RR一个Read View用到底的原因AID还在m_ids依旧不可见 反观RC,每次更新Read View,虽然第一次事务A的ID在m_ids中不可见其版本但是后续提交后再次快照读生成新的Read View事务A的ID不存在m_ids并且满足查看的条件所以快照读的版本就是事务A的版本。