MySQL学习笔记2

109 阅读5分钟

事务

事务就是一组原子性的SQL查询。事务内的语句,要么全部执行 成功,要么全部执行失败。

ACID表示原子性(atomicity)、一致性(consistency)、隔离性 (isolation)和持久性(durability)。一个运行良好的事务处理系统, 必须具备这些标准特征。

原子性(atomicity)

 一个事务必须被视为一个不可分割的最小工作单元,整个事务 中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事 务来说,不可能只执行其中的一部分操作,这就是事务的原子性。

一致性(consistency)

数据库总是从一个一致性的状态转换到另外一个一致性的状态。例子:因为事务最终没有提交,所以事务中所做的修改也不会保存到数据库中。

隔离性(isolation) 

通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的

持久性(durability)

一旦事务提交,则其所做的修改就会永久保存到数据库中。

隔离级别

在SQL标准中定义了四种隔离级别, 每一种级别都规定了一个事务中所做的修改,哪些在事务内和事务间是可见的,哪些是不可见的。

READ UNCOMMITTED(未提交读)

在READ UNCOMMITTED 级别,事务中的修改,即使没有提交, 对其他事务也都是可见的。事务可以读取未提交的数据,这也被称为脏读(Dirty Read)。

READ COMMITTED(提交读)

大多数数据库系统的默认隔离级别都是READ COMMITTED (但 MySQL不是)。READ COMMITTED 满足前面提到的隔离性的简单定 义:一个事务开始时,只能“看见”已经提交的事务所做的修改。换 句话说,一个事务从开始直到提交之前,所做的任何修改对其他事 务都是不可见的。这个级别有时候也叫做不可重复读 (nonrepeatable read),因为两次执行同样的查询,可能会得到不 一样的结果。

不可重复读演示的执行流程如下:

窗口 2 同一个事务中的两次查询,得到了不同的结果这就是不可重复读。

REPEATABLE READ(可重复读)

REPEATABLE READ 解决了脏读的问题。该级别保证了在同一个 事务中多次读取同样记录的结果是一致的。但是理论上,可重复读 隔离级别还是无法解决另外一个幻读(Phantom Read)的问题。

关于幻读,个人觉得“高性能MySQL”中的解释并不准确,这里参考另一篇博客上的解释:

在一个事务中明明没有查到主键为 X 的数据,但主键为 X 的数据就是插入不进去,就像某种幻觉一样。

幻读演示的执行流程如下:

SERIALIZABLE(可串行化)

SERIALIZABLE 是最高的隔离级别。它通过强制事务串行执 行,避免了前面说的幻读的问题。简单来说,SERIALIZABLE 会在 读取的每一行数据上都加锁,所以可能导致大量的超时和锁争用的 问题。实际应用中也很少用到这个隔离级别,只有在非常需要确保 数据的一致性而且可以接受没有并发的情况下,才考虑采用该级别。 

死锁

死锁是指两个或者多个事务在同一资源上相互占用,并请求锁定对 方占用的资源,从而导致恶性循环的现象。当多个事务试图以不同的顺 序锁定资源时,就可能会产生死锁。

InnoDB目前处理死 锁的方法是,将持有最少行级排他锁的事务进行回滚(这是相对比较简 单的死锁回滚算法)。

锁的行为和顺序是和存储引擎相关的。

事务日志

事务日志可以帮助提高事务的效率。

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

事务日志采用的是追加的方式,因此写日志的操作是磁盘上一小块区域内的顺序I/O,而不像随机I/O需要在磁盘的多个地方移动磁头,所以采用事务日志的方式相对来说要快得多。

修改数据需要写两次磁盘。

MySQL默认采用自动提交(AUTOCOMMIT )模式。也就是说,如果 不是显式地开始一个事务,则每个查询都被当作一个事务执行提交操作。

还有一些命令,在执行之前会强制执行COMMIT 提交当前的活动事务:

alter table, lock tables

MySQL可以通过执行SET TRANSACTION ISOLATION LEVEL 命令来设 置隔离级别。

隐式和显式锁定

InnoDB采用的是两阶段锁定协议(two-phase locking protocol)。在 事务执行过程中,随时都可以执行锁定,锁只有在执行COMMIT 或 者ROLLBACK 的时候才会释放,并且所有的锁是在同一时刻被释放。

之前的介绍都是隐式锁定。使用以下语句则是显示锁定:

SELECT ... LOCK IN SHARE MODE SELECT ... FOR UPDATE