ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

mysql事务小记

2021-09-17 12:30:06  阅读:159  来源: 互联网

标签:事务 log 版本号 提交 mysql 日志 redo 小记


文章目录


参考:

Mysql事务隔离级别详细解析
数据库事务与Mysql事务总结
Mysql锁总结
Mysql中的连接、实例、会话

Mysql中的实例(instance)、会话(session)、数据库与线程之间的关系

  • Mysql是单进程多线程的,Mysql实例在系统上表现就是一个服务进程

  • 一般情况下一个实例操作一个或者多个数据库,在集群情况下多个实例操作一个或者多个数据库

  • 一个实例是由线程和内存组成的

  • 在操作系统概念里,会话就是线程

  • mysql中建立一个会话是指和某个实例建立会话,一个会话可以操作一个实例上的多个数据库

  • 一个连接是指一个客户端和专有服务器的网络连接

  • 创建一个连接实际上是在某个实例中创建一个或者多个线程

  • 一个连接可以没有会话也可以有多个会话

  • 会话与事务的关系:一个会话可以创建多个事务,一个事务只能由一个会话产生,一个事务可能会产生一个或者多个线程,一个线程在同一时间只能执行一个事务

事务特点

注:Mysql事务都是指在InnoDB引擎下,MyISAM引擎不支持事务。

事务的四个特性:ACID

原子性(Atomicity):一个事务中的操作要么全部成功提交,要么全部失败回滚,不能只执行一部分。

一致性(Consistency):数据库总是从一个一致性状态转移到另一个一致性状态。

隔离性(Isolation):通常来说,一个事务中的操作在提交之前对其他事务是不可见的。

持久性(Durability):一旦事务提交,其所做的更改将会永久保存在数据库中,即使数据库崩溃也不会消失。

事务的隔离级别

并发事务带来的问题

  • 更新丢失当多个事务选择同一行,基于最初选定的值更新改行的时候,每个事务不知道彼此的存在,最后的更新会覆盖之前的更新,也就是更新丢失问题解决方法:使得一个事务处理这一行的时候其他事务等待

  • 脏读读到了其他事务未提交的操作

  • 不可重复读(针对更新操作)一个事务两次对同一个数据读取到的值不同,也就是说其他事务提交的修改对该事务是可见的

  • 幻读(针对插入操作)假设事务A对某些行的内容作了更改,但是还未提交,此时事务B插入了与事务A更改前的记录相同的记录行,并且在事务A提交之前先提交了,而这时,在事务A中查询,会发现好像刚刚的更改对于某些数据未起作用,但其实是事务B刚插入进来的,让用户感觉很魔幻,感觉出现了幻觉,这就叫幻读。

事务隔离级别

以下隔离级别从上到下隔离度逐渐变强,并发度逐渐变弱。

  • 读未提交(READ CUNCOMMITTED)

  • 读已提交(READ COMMITTED)

  • 可重复读(REPEATABLE READ)Mysql的默认隔离级别

  • 串行化(SERIALIZABLE)

隔离级别脏读不可重复读幻读
读未提交可能可能可能
读已提交不可能可能可能
可重复读不可能不可能可能
串行化不可能不可能不可能

多版本并发控制(MVCC)

InnoDB的MVCC是通过在每行记录后面保存两个隐藏的列来实现。这两个列一个保存了行的创建时间,一个保存行的过期时间(删除时间),当然存储的并不是真实的时间而是系统版本号(system version number)。

MVCC只工作在读已提交和可重复读两种隔离级别下。他是行级锁的一个变种,很多情况下避免了加锁操作。

可重复读下MVCC的工作方式

select:只查找版本号早于当前事务版本的数据行,这样可以保证事务读取的行要么是在开始事务之前存在的,要么是当前事务修改的;行的删除版本号要么未定义,要么大于当前版本号,这样可以确保事务读取到的行在事务开始之前没有被删除。

insert:为插入的每一行保存当前系统版本号作为行版本号。

delete:为删除的每一行保存当前系统版本号为删除版本号。

update:为插入的一行新纪录保存当前系统版本号作为行版本号,同时保存当前系统版本号到原来的行作为删除标识。

可重复读和读已提交在MVCC工作方式上的不同

二者最主要的区别是在快照的创建上,可重复读只在事务开始时创建一次,而读已提交在每次执行语句的时候都创建一次。

对于一个快照来说,它能够读到那些版本数据,要遵循以下规则:

  1. 当前事务内的更新,可以读到;

  2. 版本未提交,不能读到;

  3. 版本已提交,但是却在快照创建后提交的,不能读到;

  4. 版本已提交,且是在快照创建前提交的,可以读到;

事务日志及事务实现原理

  • 使用事务日志使得存储引擎在修改表的时候只需要修改其内存拷贝,再把该修改行为记录到硬盘的事务日志上,而不用每次都将修改的数据本身持久化到磁盘。

  • 事务日志采用追加的方式,写日志的操作时磁盘上一小块区域内的顺序IO,而不是随机IO,所以采用事务日志的方式相对来说更快。

  • 事务日志持久之后,内存中的数据会慢慢刷到磁盘。

  • 如果数据的修改以及记录到事务日志并持久化,但是数据本身没有写回到磁盘,此时系统崩溃,存储引擎在重启的时候可以自动恢复这一部分修改的日志。

mysql的事务实现原理

事务的原子性、一致性和持久性则是通过事务日志实现。说到事务日志,不得不说的就是redo和undo。

  • redolog

在innoDB的存储引擎中,事务日志通过重做(redo)日志和innoDB存储引擎的日志缓冲(InnoDB Log Buffer)实现。事务开启时,事务中的操作,都会先写入存储引擎的日志缓冲中,在事务提交之前,这些缓冲的日志都需要提前刷新到磁盘上持久化,这就是DBA们口中常说的“日志先行”(Write-Ahead Logging)。当事务提交之后,在Buffer Pool中映射的数据文件才会慢慢刷新到磁盘。此时如果数据库崩溃或者宕机,那么当系统重启进行恢复时,就可以根据redo log中记录的日志,把数据库恢复到崩溃前的一个状态。未完成的事务,可以继续提交,也可以选择回滚,这基于恢复的策略而定。

在系统启动的时候,就已经为redo log分配了一块连续的存储空间,以顺序追加的方式记录Redo Log,通过顺序IO来改善性能。所有的事务共享redo log的存储空间,它们的Redo Log按语句的执行顺序,依次交替的记录在一起。如下一个简单示例:

记录1:<trx1, insert…>

记录2:<trx2, delete…>

记录3:<trx3, update…>

记录4:<trx1, update…>

记录5:<trx3, insert…>

  • undolog

undo log主要为事务的回滚服务。在事务执行的过程中,除了记录redo log,还会记录一定量的undo log。undo log记录了数据在每个操作前的状态,如果事务执行过程中需要回滚,就可以根据undo log进行回滚操作。单个事务的回滚,只会回滚当前事务做的操作,并不会影响到其他的事务做的操作。

以下是undo+redo事务的简化过程

假设有2个数值,分别为A和B,值为1,2

  1. start transaction;

  2. 记录 A=1 到undo log;

  3. update A = 3;

  4. 记录 A=3 到redo log;

  5. 记录 B=2 到undo log;

  6. update B = 4;

  7. 记录B = 4 到redo log;

  8. 将redo log刷新到磁盘

  9. commit

在1-8的任意一步系统宕机,事务未提交,该事务就不会对磁盘上的数据做任何影响。如果在8-9之间宕机,恢复之后可以选择回滚,也可以选择继续完成事务提交,因为此时redo log已经持久化。若在9之后系统宕机,内存映射中变更的数据还来不及刷回磁盘,那么系统恢复之后,可以根据redo log把数据刷回磁盘。

redolog保障了事务的持久型和一致性,undolog保障了事务的原子性

事务的使用

设置隔离级别

设置隔离级别的语句:set [作用域] transaction isolation level [事务隔离级别],SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}

其中作用域可以是当前session也可以是global全局的例如设置全局隔离级别为读已提交:

mysql> set global transaction isolation level read committed

事务的开始与提交

begin不代表事务的开始,事务开始于begin命令之后第一条语句执行的时候,以下语句中select * from xxx才是事务的开始

begin;
select * from xxx; 
commit; -- 或者 rollback;

可以查询当前有多少事务在运行

select * from information_schema.innodb_trx;

标签:事务,log,版本号,提交,mysql,日志,redo,小记
来源: https://blog.csdn.net/vilin_FHSI/article/details/120346373

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有