MySQL的事务实现严格遵循ACID特性,即原子性(atomicity),一致性(consistency),隔离性(isolation),持久性(durability)。为了避免一上来就陷入对ACID的概念理解,我们直接先谈MySQL事务实现机制。
MySQL提供了两种事务型的存储引擎:InnoDB和NDB Cluster。另外还有一些第三方存储引擎也支持事务,比较知名的包括XtraDB和PBXT。下面以InnoDB来说明。
MySQL会最大程度的使用缓存机制来提高数据库的访问效率,但是万一数据库发生断电,因为缓存的数据没有写入磁盘,导致缓存在内存中的数据丢失而导致数据不一致怎么办?
InnoDB主要是通过事务日志实现ACID特性,事务日志可以帮助提高事务的效率。使用事务日志,存储引擎在修改表的数据时只需要修改其内存拷贝,再把该修改行为记录到持久在硬盘上的事务日志中,而不用每次都将修改的数据本身持久到磁盘。(MySQL事务日志Undo&Redo)
事务日志采用追加的方式,因此写日志的操作是磁盘上一小块区域的顺序I/O,而不像随机I/O需要在磁盘的多个地方移动磁头。所以事务日志的方式相对来说要快得多。事务日志持久以后,内存中被修改的数据在后台可以慢慢的刷回磁盘。目前大多数存储引擎是这样实现的,我们称之为预写式日志,即修改数据需要写两次磁盘。
事务日志包括重做日志redo和回滚日志undo,Redo记录的是已经全部完成的事务,就是执行了commit的事务,记录文件是ib_logfile0 ib_logfile1。Undo记录的是已部分完成并且写入硬盘的未完成的事务,默认情况下回滚日志是记录在表空间中的(共享表空间或者独享表空间)。
一般情况下,mysql在崩溃之后,重启服务,innodb通过回滚日志undo将所有已完成并写入磁盘的未完成事务进行rollback,然后redo中的事务全部重新执行一遍即可恢复数据,但是随着redo的量增加,每次从redo的第一条开始恢复就会浪费长的时间,所以引入了checkpoint机制。
一般业务运行过程中,当业务需要对某张表的某行数据进行修改的时候,innodb会先将该数据从磁盘读取到缓存中去,然后在缓存中对这条数据进行修改,这样缓存中的数据就和磁盘的数据不一致了,这个时候缓存中的数据就称为dirty page,只有当脏页统一刷新到磁盘中才会是clean page。
Checkpoint:如果在某个时间点,脏页的数据被刷新到了磁盘,系统就把这个刷新的时间点记录到redo log的结尾位置,在进行恢复数据的时候,checkpoint时间点之前的数据就不需要进行恢复了,可以缩短时间。
Innodb_log_buffer_size 重做日志缓存大小
Innodb_log_file_size redo log文件大小 文件越大 数据恢复的时间越长
Innodb_log_file_group redo log文件数量 默认是2个 ib_logfile0 ib_logfile1
事务日志的的机制实际上是满足的事务的原子性和持久性,即要么都成功,要么都失败。而谈到事务的一致性和隔离性,就要谈到“锁”了。
InnoDB采用的是两阶段锁定协议。在事务执行过程中,随时都可以执行锁定,锁只有在执行COMMIT或ROLLBACK时才会释放,并且所有的锁同一时刻释放。InnoDB会根据隔离级别在需要的时候自动加锁。
MySQL的大多数事务型存储引擎实现的都不是简单的行级锁。基于提升并发性能的考虑,它们一般都同时实现了多版本并发控制(MVCC)。MVCC实现了非阻塞的读操作,写操作也只锁定必要的行。MVCC的实现,是通过保存数据在某个时间点的快照来实现的。对于InnoDB,是通过在每行记录后面保存两个隐藏的列来实现的。这两个列,一个保存了行的创建时间,一个保存了行的过期时间(或删除时间)。当然存储的并不是实际时间值,而是系统版本号。每开始一个新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会作为事务的版本号,用来和查询到的每行记录的版本号进行比较。下面看一下在MySQL默认隔离级别REPEATABLE READ下,MVCC具体是如何操作的。
SELECT
InnoDB会根据以下两个条件检查每行记录:
a. InnoDB只查找版本早于当前事务版本的数据行(也就是,行的系统版本号<=事务的系统版本好),这样可 以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或修改过的。
b. 行的删除版本要么未定义,要么大于当前事务版本号。这样可以确保事务读取到的行,在事务开始之前未被 删除。
只有符合上述两个条件的记录,才能返回作为查询结果。
INSERT
InnoDB为新插入的每一行保存当前系统版本号作为行版本号。
DELETE
InnoDB为删除的每一行保存当前系统版本号作为删除标识。
UPDATE
InnoDB为插入一行新记录,保存当前系统版本号作为行版本号,同时保存当前系统版本号到原来的行作为行 删除标识。
保存这两个额外系统版本号,使大多数读操作都可以不用加锁。这样读操作简单而性能好,也能保证读到符合标准的行。不足之处是需要额外的存储空间,需要做更多的行检查工作,以及一些额外的维护工作。另外,MVCC只在REPEATABLE READ和READ COMMITED两个隔离级别下工作。其他两个隔离级别都和MVCC不兼容,因为READ UNCOMMITED纵是读取到最新的数据行,而不是符合当前事务版本的数据行,而SERIALIZABLE则会对所有读取的行都加锁。
好了,相信你对MySQL事务实现机制有些了解了,下面摘抄两段知乎上关于ACID的理解。
--------------
定义:数据库一致性(Database Consistency)是指事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。
数据库状态如何变化?每一次数据变更就会导致数据库的状态迁移。如果数据库的初始状态是C0,第一次事务T1的提交就会导致系统生成一个SYSTEM CHANGE NUMBER(SCN),这是数据库状态从C0转变成C1。执行第二个事务T2的时候数据库状态从C1变成C2,以此类推,执行第Tn次事务的时候数据库状态由C(n-1)变成Cn。
定义一致性主要有2个方面,一致读和一致写。
一致写:事务执行的数据变更只能基于上一个一致的状态,且只能体现在一个状态中。T(n)的变更结果只能基于C(n-1),C(n-2), ...C(1)状态,且只能体现在C(n)状态中。也就是说,一个状态只能有一个事务变更数据,不允许有2个或者2个以上事务在一个状态中变更数据。至于具体一致写基于哪个状态,需要判断T(n)事务是否和T(n-1),T(n-2),...T(1)有依赖关系。
一致读:事务读取数据只能从一个状态中读取,不能从2个或者2个以上状态读取。也就是T(n)只能从C(n-1),C(n-2)... C(1)中的一个状态读取数据,不能一部分数据读取自C(n-1),而另一部分数据读取自C(n-2)。
摆事实
一致写:
定义100个事务T(1)...T(100)实现相同的逻辑 update table set i=i+1,i的初始值是0,那么并发执行这100个事务之后i的值是多少?可能很容易想到是100。那么怎么从一致性角度去理解呢?
数据库随机调度到T(50)执行,此时数据库状态是C(0),而其它事务都和T(50)有依赖关系,根据写一致性原理,其它事务必须等到T(50)执行完毕后数据库状态变为C(1)才可以执行。因此数据库利用锁机制阻塞其它事务的执行。直到T(50)执行完毕,数据库状态从C(0)迁移到C(1)。数据库唤醒其它事务后随机调度到T(89)执行,以此类推直到所有事务调度执行完毕,数据库状态最终变为C(100)。
一致读:
还是上面的例子,假设T(1)...T(100)顺序执行,在不同的时机执行select i from table,我们看到i的值是什么?
1. T(1)的执行过程中。数据库状态尚未迁移,读到的i=0
2. T(1)执行完毕,T(2)的执行过程中,数据库状态迁移至C(1),读到的i=1
---------------
首先介绍事务,什么是事务,事务就是DBMS当中用户程序的任何一次执行,事务室DBMS能看到的基本修改单元。
事务是指对系统进行的一组操作,为了保证系统的完整性,事务需要具有ACID特性,具体如下:
1. 原子性(Atomic)
一个事务包含多个操作,这些操作要么全部执行,要么全都不执行。实现事务的原子性,要支持回滚操作,在某个操作失败后,回滚到事务执行之前的状态。
回滚实际上是一个比较高层抽象的概念,大多数DB在实现事务时,是在事务操作的数据快照上进行的(比如,MVCC),并不修改实际的数据,如果有错并不会提交,所以很自然的支持回滚。
而在其他支持简单事务的系统中,不会在快照上更新,而直接操作实际数据。可以先预演一边所有要执行的操作,如果失败则这些操作不会被执行,通过这种方式很简单的实现了原子性。
2. 一致性(Consistency)
一致性是指事务使得系统从一个一致的状态转换到另一个一致状态。事务的一致性决定了一个系统设计和实现的复杂度。事务可以不同程度的一致性:
强一致性:读操作可以立即读到提交的更新操作。
弱一致性:提交的更新操作,不一定立即会被读操作读到,此种情况会存在一个不一致窗口,指的是读操作可以读到最新值的一段时间。
最终一致性:是弱一致性的特例。事务更新一份数据,最终一致性保证在没有其他事务更新同样的值的话,最终所有的事务都会读到之前事务更新的最新值。如果没有错误发生,不一致窗口的大小依赖于:通信延迟,系统负载等。
其他一致性变体还有:
单调一致性:如果一个进程已经读到一个值,那么后续不会读到更早的值。
会话一致性:保证客户端和服务器交互的会话过程中,读操作可以读到更新操作后的最新值。
3. 隔离性(Isolation)
并发事务之间互相影响的程度,比如一个事务会不会读取到另一个未提交的事务修改的数据。在事务并发操作时,可能出现的问题有:
脏读:事务A修改了一个数据,但未提交,事务B读到了事务A未提交的更新结果,如果事务A提交失败,事务B读到的就是脏数据。
不可重复读:在同一个事务中,对于同一份数据读取到的结果不一致。比如,事务B在事务A提交前读到的结果,和提交后读到的结果可能不同。不可重复读出现的原因就是事务并发修改记录,要避免这种情况,最简单的方法就是对要修改的记录加锁,这回导致锁竞争加剧,影响性能。另一种方法是通过MVCC可以在无锁的情况下,避免不可重复读。
幻读:在同一个事务中,同一个查询多次返回的结果不一致。事务A新增了一条记录,事务B在事务A提交前后各执行了一次查询操作,发现后一次比前一次多了一条记录。幻读是由于并发事务增加记录导致的,这个不能像不可重复读通过记录加锁解决,因为对于新增的记录根本无法加锁。需要将事务串行化,才能避免幻读。
事务的隔离级别从低到高有:
Read Uncommitted:最低的隔离级别,什么都不需要做,一个事务可以读到另一个事务未提交的结果。所有的并发事务问题都会发生。
Read Committed:只有在事务提交后,其更新结果才会被其他事务看见。可以解决脏读问题。
Repeated Read:在一个事务中,对于同一份数据的读取结果总是相同的,无论是否有其他事务对这份数据进行操作,以及这个事务是否提交。可以解决脏读、不可重复读。
Serialization:事务串行化执行,隔离级别最高,牺牲了系统的并发性。可以解决并发事务的所有问题。
通常,在工程实践中,为了性能的考虑会对隔离性进行折中。
4. 持久性(Durability)
事务提交后,对系统的影响是永久的。
相关推荐
InnoDB支持ACID(原子性、一致性、隔离性、持久性)特性,确保了事务的可靠执行。事务隔离级别有四种:读未提交(READ UNCOMMITTED)、读已提交(READ COMMITTED)、可重复读(REPEATABLE READ,MySQL默认)和串行化...
MySQL通过事务的ACID特性来确保操作的一致性、隔离性、持久性和原子性。其中: - **原子性**(Atomicity):事务中的所有操作要么全部完成,要么一个也不完成。 - **一致性**(Consistency):事务始终使数据库从一...
首先,InnoDB的事务处理机制遵循ACID(原子性、一致性、隔离性、持久性)原则,确保了数据操作的完整性和准确性。书中会详细讲解四种隔离级别——读未提交(READ UNCOMMITTED)、读已提交(READ COMMITTED)、可重复...
教程会解释ACID属性,以及如何在MySQL中使用BEGIN、COMMIT、ROLLBACK等语句管理事务。同时,还会介绍并发控制机制,如锁定和死锁处理。 七、备份与恢复 数据安全是数据库管理的重要环节。本教程将介绍如何使用...
4. **事务与并发控制**:MySQL支持ACID(原子性、一致性、隔离性和持久性)特性,笔记会涉及事务的四大操作(BEGIN、COMMIT、ROLLBACK、SAVEPOINT)和并发控制机制,如锁定和MVCC(多版本并发控制)。 5. **存储...
本资料包“mysql技术内幕innodb存储引擎学习.zip”显然是针对深入理解InnoDB存储引擎的学习资源,其中可能包含详细的技术讲解、实践案例和相关教程。 InnoDB存储引擎的核心特性包括: 1. **事务支持**:InnoDB提供...
根据提供的标题“MySQL 技术内幕:InnoDB存储引擎”,我们可以深入探讨InnoDB存储引擎的相关知识点,包括其架构原理、特点、应用场景以及优化方法等方面。 ### InnoDB存储引擎概述 InnoDB是MySQL中最常用的一种...
2. **存储引擎**:MySQL 5引入了InnoDB作为默认的事务处理存储引擎,提供了行级锁定和ACID(原子性、一致性、隔离性和持久性)特性。此外,MyISAM、MEMORY和ARCHIVE等其他引擎各有特点,适用于不同的应用场景。 3. ...
MySQL通过ACID特性(原子性、一致性、隔离性、持久性)来保证事务的正确执行。了解事务的隔离级别和回滚机制是掌握MySQL高级用法的关键。 ### 索引与性能 索引是提高数据库查询速度的重要手段。合理的索引设计可以...
2. **《MySQL技术内幕InnoDB存储引擎》**:InnoDB是MySQL中最主要的事务处理存储引擎,支持行级锁定和ACID特性。本书深入剖析了InnoDB的内部工作原理,包括表空间、页、行格式、索引结构(B+树)、事务处理、锁机制...
InnoDB是MySQL中最主要的事务处理存储引擎,支持行级锁定,提供ACID(原子性、一致性、隔离性、持久性)事务。本书详细阐述了InnoDB的索引结构,包括B+树索引和自适应哈希索引,以及如何优化查询性能。此外,它还...
InnoDB是MySQL的默认存储引擎,它支持ACID(原子性、一致性、隔离性和持久性)事务,这是许多企业级应用所必需的特性。InnoDB使用聚集索引,其中每个索引条目都包含行数据,这与MyISAM等其他存储引擎不同。此外,...
MySQL是世界上最受欢迎的开源数据库系统之一,而InnoDB存储引擎是其最常用的核心组件,尤其在处理事务性和ACID(原子性、一致性、隔离性、持久性)需求方面。本资料包包含三本关于MySQL和InnoDB的重要书籍,分别是...
5. **事务管理**:在InnoDB存储引擎中,MySQL支持ACID特性,保证事务的原子性、一致性、隔离性和持久性。这部分将详细讲解事务的开始、提交、回滚以及并发控制中的死锁检测与解决。 6. **并发控制**:MySQL使用MVCC...
4. **事务与并发控制**:理解ACID特性(原子性、一致性、隔离性、持久性),熟悉事务的使用,包括BEGIN、COMMIT、ROLLBACK以及不同的事务隔离级别。 5. **视图与存储过程**:学习创建和使用视图,以简化复杂的查询...
《MySQL技术内幕:sampdb数据库》是一本深入探讨MySQL数据库管理与应用的书籍,其中以 sampdb 数据库作为示例,帮助读者理解并掌握数据库设计、数据操作、查询优化、事务处理、存储引擎以及安全控制等核心概念。...
2. **事务处理与并发控制**:MySQL 8增强了事务处理能力,支持ACID(原子性、一致性、隔离性和持久性)特性。我们将讨论事务的四种隔离级别、死锁检测和InnoDB存储引擎的行级锁定。 3. **性能优化**:MySQL 8引入了...
InnoDB是MySQL中最常用的事务型存储引擎,支持ACID(原子性、一致性、隔离性和持久性)特性,尤其在大数据量、高并发的业务场景下,其性能和稳定性至关重要。 1. **InnoDB存储结构** InnoDB存储引擎的核心组成部分...
《MySQL技术内幕-InnoDB存储引擎》是一本深入探讨MySQL数据库InnoDB存储引擎的权威书籍,而`py_innodb_page_info.zip`则是该书中提到的一个实用工具,用于分析InnoDB存储引擎的数据页信息。这个Python工具帮助我们...
1. **MySQL技术内幕InnoDB存储引擎.pdf**:这是一份关于MySQL数据库中InnoDB存储引擎的技术文档。InnoDB是MySQL中最常用的存储引擎,支持事务处理和行级锁定,适合大数据量和高并发的业务场景。学习这个,学生可以...