MYSQL事务隔离与事务日志

一 序:

在看《高性能MySQL》书的时候,讲到了MVCC。这个概念我是模糊的,脑子印象就是读不加锁,读写不冲突。

咋实现的?看书专门整理下,后面加上网上关于MVCC的理解。

二 事务隔离级别

2.1 事务

 数据库事务(Database Transaction),是指作为单个逻辑工作单元执行的一系列操作,要么完全执行,要么完全地不执行。

原子性(Atomicity)
一个事物被视为不可分割的最小工作单元,整个事务中所有操作要么全部提交成功,要么全部失败回滚。不可能只执行其中的一部分操作。
一致性(Consistency)
一致性是指事务必须使数据库从一个一致的状态变到另外一个一致的状态,也就是执行事务之前和之后的状态都必须处于一致的状态。
隔离性(Isolation)
隔离性通常来说,一个事务所做的修改在提交之前,对其他事务是不可见的。
持久性(Durability)
持久性是指一个事务一旦被提交了,那么对于数据库中的数据改变就是永久性的,即便是在数据库系统遭遇到故障的情况下也不会丢失提交事务的操作。

书上的举例还是经典的银行转账的例子,当然上面介绍的是数据库的通用原则,并非MySQL专有特性。

2.2 mysql 使用事务

MySQL默认采用自动提交(autocommit )模式,当然可以修改启用或者禁用自动修改模式。

show variables like 'autocommit'
    -> ;
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set (0.00 sec)

回滚举例:

set autocommit = 0 禁止自动提交
start transaction;
update account set money=money-100 where name="justin";
rollback;

2.3 事务隔离级别

Read Uncommitted(读取未提交内容)
       在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。
Read Committed(读取提交内容)
       这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。
Repeatable Read(可重读)
       这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。
Serializable(可串行化) 
       这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
         这四种隔离级别采取不同的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。例如:
         脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。
         不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。

         幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。


mysql 中的隔离级别设置:

查看 select @@tx_isolation;

select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set (0.00 sec)

修改隔离级别

set  [global | session]  transaction isolation level 隔离级别名称;

三  事务日志

       事务日志用于保证事务的可靠性,在进行事务操作时先将操作写进事务日志,而事务日志会记录老数据和新数据从而实现回滚。并且不用每次都将修改的数据本身持久到磁盘,事务日志采用的是追加的方式记录。因此写日志操作时磁盘上一小块区域内的顺序I/O,而不像随机I/O需要在磁盘的多个地方移动磁头。所以采用事务日志的方式相对来说要快得多。事务日志持久以后,内存中被修改的数据在后台可以慢慢地刷回磁盘。目前大多数存储引擎都是这样设计的。我们通常称之为预写式日志,修改数据需要写两次磁盘。

      如果数据的修改意见记录到事务日志并持久化,但数据本身还没有写回磁盘,此时系统崩溃,存储引擎在重启时能够自动恢复这部分修改的数据。具体的恢复方式视存储引擎而定。

   以上是书上1.3.3事务日志的内容,没有展开。其实这块内容挺多的。开个头,后续在整理吧

MySQL中有六种日志文件,分别是:重做日志(redo log) 回滚日志(undo log) 二进制日志(binlog) 错误日志(errorlog) 慢查询日志(slow query log) 一般查询日志(general log) 中继日志(relay log)。其中重做日志和回滚日志与事务操作息息相关,二进制日志也与事务操作有一定的关系。参见网上这篇文章《MySQL主库CrashSafe与Binlog关系?

3.1 redo

作用:确保事务的持久性。防止在发生故障的时间点,尚有脏页未写入磁盘,在重启mysql服务的时候,根据redo log进行重做,从而达到事务的持久性这一特性。

内容:物理格式的日志,记录的是物理数据页面的修改的信息,其redo log是顺序写入redo log file的物理文件中去的。

什么时候产生:事务开始之后就产生redo log,redo log的落盘并不是随着事务的提交才写入的,而是在事务的执行过程中,便开始写入redo log文件中。

对应的物理文件:data目录下ib_logfile*。

关于文件的大小和数量,由以下两个参数配置:
innodb_log_file_size 重做日志文件的大小。
innodb_mirrored_log_groups 指定了日志镜像文件组的数量,默认1

上面提到的Dirty page:脏页 什么意思呢?
       一般业务运行过程中,当业务需要对某张的某行数据进行修改的时候,innodb会先将该数据从磁盘读取到缓存中去,然后在缓存中对这条数据进行修改,这样缓存中的数据就和磁盘的数据不一致了,这个时候缓存中的数据就称为dirty page,只有当脏页统一刷新到磁盘中才会是clean page。
     一般情况下,mysql在崩溃之后,重启服务,innodb通过回滚日志undo将所有已完成并写入磁盘的未完成事务进行rollback,然后redo中的事务全部重新执行一遍即可恢复数据,但是随着redo的量增加,每次从redo的第一条开始恢复就会浪费长的时间,所以引入了checkpoint机制。

Checkpoint:如果在某个时间点,脏页的数据被刷新到了磁盘,系统就把这个刷新的时间点记录到redo log的结尾位置,在进行恢复数据的时候,checkpoint时间点之前的数据就不需要进行恢复了,可以缩短时间。

3.2 undo log

undo log不是redo log的逆向过程,其实它们都算是用来恢复的日志:
1.redo log通常是物理日志,记录的是数据页的物理修改,而不是某一行或某几行修改成怎样怎样,它用来恢复提交后的物理数据页(恢复数据页,且只能恢复到最后一次提交的位置)。

2.undo用来回滚行记录到某个版本。undo log一般是逻辑日志,根据每行记录进行记录。

作用:提供回滚和多个行版本控制(MVCC)。

内容:逻辑格式的日志,在执行undo的时候,仅仅是将数据从逻辑上恢复至事务之前的状态,而不是从物理页面上操作实现的,这一点是不同于redo log的。

什么时候产生:事务开始之前,将当前是的版本生成undo log,undo 也会产生 redo 来保证undo log的可靠性

文件:从MySQL 5.6开始,Undo使用的表空间可以分离为独立的Undo log文件。

存储:为了提高undo log的并发操作,InnoDB将Undo log拆分为很多的浮动程序段(relocatable segment)来进行维护,每个RSEG当中又有多个Undo log slot,每个事务占用一个slot。

这里内容还很多。待续。。。

猜你喜欢

转载自blog.csdn.net/bohu83/article/details/80923440