一、事务四大特性
-
原子性(Atomicity): 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
-
一致性(Consistency): 执行事务后,数据库从一个正确的状态变化到另一个正确的状态;
-
隔离性(Isolation): 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
-
持久性(Durability): 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
二、事务隔离级别
Mysql默认隔离级别是可重复度
SQL 标准定义了四个隔离级别:
-
READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
-
READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。
-
REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
-
SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。
隔离级别 | 脏读 | 不可重复读 | 幻影读 |
---|---|---|---|
READ-UNCOMMITTED(读未提交) | √ | √ | √ |
READ-COMMITTED(读已提交) | × | √ | √ |
REPEATABLE-READ(可重复读) | × | × | √ |
SERIALIZABLE(可串行化) | × | × | × |
三、并发事务存在的问题
-
脏读:一个事务读取数据并且对数据进行了修改,这个修改对其他事务来说是可见的,即使当前事务没有提交。这时另外一个事务读取了这个还未提交的数据,但第一个事务突然回滚,导致数据并没有被提交到数据库,那第二个事务读取到的就是脏数据,这也就是脏读的由来。
-
丢失修改(Lost to modify): 指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。 例如:事务1读取某表中的数据A=20,事务2也读取A=20,事务1修改A=A-1,事务2也修改A=A-1,最终结果A=19,事务1的修改被丢失。
-
不可重复读(Unrepeatableread): 指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。
-
幻读(Phantom read): 幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。
不可重复读和幻读区别:不可重复读的重点是修改比如多次读取一条记录发现其中某些列的值被修改,幻读的重点在于新增或者删除比如多次读取一条记录发现记录增多或减少了。
四、事务回滚(undolog)
MySQL的undo log(或称为rollback segment)是一种用于实现事务回滚、MVCC(多版本并发控制)和隔离级别等功能的日志文件。在MySQL中,每个事务都会维护一个undo log,用于记录事务执行前的数据状态。当事务执行过程中发生错误或者事务回滚时,MySQL就可以使用这些undo log信息,将数据恢复到事务执行之前的状态。
在MySQL中,InnoDB存储引擎通过undo log实现了MVCC机制。通过在每个数据行上保存多个版本的数据,InnoDB可以实现对不同事务对同一行数据的并发访问,并保证每个事务读取到的数据都是一致的。此外,在实现事务的原子性和一致性方面,undo log也扮演了重要的角色。
总之,undo log是MySQL中非常重要的一种日志机制,它保证了MySQL的事务性和并发性。
回滚日志作用:
-
能够在发生错误或者用户执行 ROLLBACK 时提供回滚相关的信息
-
在整个系统发生崩溃、数据库进程直接被杀死后,当用户再次启动数据库进程时,还能够立刻通过查询回滚日志将之前未完成的事务进行回滚,这也就需要回滚日志必须先于数据持久化到磁盘上,是我们需要先写日志后写数据库的主要原因。
五、事务日志(binlog)
MySQL的binlog(Binary Log,二进制日志)是一种很重要的组件,因为它记录了数据库的所有变更操作(如插入、更新、删除等),可以通过解析binlog文件内容来获得数据库的变更历史,并且可以用于数据恢复、数据同步等场景。
binlog文件类似于数据库的事务日志,记录了所有的变更操作,包括对表的DDL操作和对数据的DML操作。它是MySQL在混合日志和归档日志之前的基础日志形式,被用于所有类型的复制和同步, 包括一主多从、多主互备、分布式等情况。
binlog文件包含了一些关键信息,比如从哪个数据库、哪个表进行的操作,以及具体的修改内容。这些信息可以通过解析binlog文件来获得,通常可以使用一些工具,如mysqlbinlog等来进行解析。
通过binlog文件的解析可以实现许多功能,如:
-
数据备份:使用binlog可以将数据库的变更记录下来,然后可以使用这些日志实现全量备份和增量备份。
-
数据恢复:如果因为某些原因导致了数据的丢失,可以使用之前备份的binlog文件及其他相关数据来进行恢复操作。
-
数据同步:binlog文件可以用于在多个MySQL实例之间进行数据复制和同步,如一主多从模式。
总的来说,MySQL binlog是一个很重要的特性,可以帮助开发者和管理员实现对数据变更的可靠记录、备份和恢复,以及进行数据同步等功能。
六、重做日志(redolog)
MySQL的redo log(重做日志)是数据库的一种日志记录机制,用于在发生系统崩溃或断电等异常情况下,保证数据的完整性和一致性。它是InnoDB引擎的一个重要组成部分,既是MySQL实现ACID(原子性、一致性、隔离性和持久性)的重要手段之一,也是MySQL高效执行事务的保证。
redo log保存的是InnoDB引擎数据页的物理修改信息,当一个事务提交后,MySQL会将其对InnoDB引擎中的数据页所做的修改记录到redo log中。redo log记录的是物理操作,而不是逻辑操作,它包含了修改的表的信息、修改的页号、偏移地址、修改前数据和修改后数据等信息。当MySQL服务突然中断或异常,系统重启之后,可以使用redo log中的信息来恢复未写入磁盘的事务提交的数据,保证数据的完整性和一致性。redo log也是InnoDB支持崩溃恢复和数据持久化的重要手段之一。
MySQL的InnoDB引擎会将redo log分成多个文件组,每个文件组包含多个redo log文件,可以通过配置参数来调整redo log的大小、数量、切换条件等。
总的来说,redo log是MySQL实现事务原子性、一致性、隔离性和持久性的重要手段,也是MySQL支持崩溃恢复和数据持久化的重要保证。掌握redo log的特性和使用方法对于MySQL数据库管理员和开发人员来说是非常重要的。