目录
一、什么是事务?
事务的提交
原子性
回滚
特殊情况1:
特殊情况2:
隔离性
读未提交
读提交
可重复读
串行化
总结:
一致性
事务就是一组DML语句组成,这些语句在逻辑上存在相关性,这一组DML语句要么全部成功,要么全部 失败,是一个整体。
这句话是不是很熟悉,这不就是原子性吗,一个操作要么做完要么不做,不存在做了一部分的情况。
上面的概念可以理解为:
一个SQL语句或者多个SQL语句的集合,就是集合。
但是,一个完整的事务,绝对不是简单的 sql 集合,还需要满足如下四个属性:
原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中 间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个 事务从来没有执行过一样。
一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工 作。
隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务 并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交( Read uncommitted )、读提交( read committed )、可重复读( repeatable read )和串行化 ( Serializable )。
持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
上面四个属性,可以简称为 ACID 。
原子性(Atomicity,或称不可分割性);
一致性(Consistency);
隔离性(Isolation,又称独立性);
持久性(Durability)。
注意:原子性、一致性和隔离性是手段,目的是保持事务开始之前和事务结束之后的数据一致性。
可以查看Mysql中支持的引擎。
InnoDB中支持transactions(事务),还会支持锁,毕竟隔离性必须要有锁的帮助。
事务的提交方式常见的有两种:
自动提交 手动提交
查看事务提交方式
用 SET 来改变 MySQL 的自动提交模式:
为了更好的演示,我们先将隔离级别设为最低,因为默认的隔离级别会影响我们对事务的原子性和持久性的实验。
set global transaction isolation level READ UNCOMMITTED;为设置隔离级别
select @@tx_isolation;为查看隔离级别。
注意设置完成需要重启mysql。
创建测试表。
启动事务。
or
之后的语句都属于该事务的一部分。
开始回滚。
这里就不演示了。
我们的自动提交为开启状态:
此时我们的表格里有数据。
并没有提交事务。
一旦Mysql崩溃,再次打开Mysql检查表格中的数据,会发现在事务中插入的数据做出的操作都会回滚到最初的状态,开启事务的时候的状态。数据会自动回滚。
我们的自动提交为:
此时我们的表格里有数据。
但是提交了事务。
Mysql崩溃,我们会发现数据存在,并没有回滚,这是事务的持久性的一个体现。
这里的autocommit有什么用呢,它不影响用户手动开启事务(begin.....commit),它只会影响到单个SQL语句。
autocommit为自动提交.
autocommit不为自动提交.
证明autocommit与单SQL语句有关.
事务有隔离级别:
读未提交【Read Uncommitted】: 在该隔离级别,所有的事务都可以看到其他事务没有提交的 执行结果。(实际生产中不可能使用这种隔离级别的),但是相当于没有任何隔离性,也会有很多 并发问题,如脏读,幻读,不可重复读等,我们上面为了做实验方便,用的就是这个隔离性。
读提交【Read Committed】 :该隔离级别是大多数数据库的默认的隔离级别(不是 MySQL 默 认的)。它满足了隔离的简单定义:一个事务只能看到其他的已经提交的事务所做的改变。这种隔离 级别会引起不可重复读,即一个事务执行时,如果多次 select, 可能得到不同的结果。
可重复读【Repeatable Read】: 这是 MySQL 默认的隔离级别,它确保同一个事务,在执行 中,多次读取操作数据时,会看到同样的数据行。但是会有幻读问题。
串行化【Serializable】: 这是事务的最高隔离级别,它通过强制事务排序,使之不可能相互冲突, 从而解决了幻读的问题。它在每个读的数据行上面加上共享锁,。但是可能会导致超时和锁竞争 (这种隔离级别太极端,实际生产基本不使用)
只是用来干嘛的?
事务一旦执行起来,因为是一系列SQL语句组成的,执行就要时间.就会有三种状态,事务执行前、事务执行中、事务执行后.在这三个阶段访问数据,究竟会不会不同,这要通过隔离级别来界定.
所谓读未提交,为该事务未提交,在外部可以看到已经在事务中修改的数据.
在此之前我们需要设置隔离级别.
set global transaction isolation level read uncommitted;
之后需要重启.我们此时设置的是全局的隔离级别,隔离级别还有会话的隔离级别,设置会话的隔离级别只会影响单个会话的隔离级别.这次的实验需要开启多个会话,所以要设置全局的隔离级别.
一个事务在执行中,读到另一个执行中事务的更新(或其他操作)但是未commit的数据,这种现象叫做脏读 (dirty read).
只有提交过后才能查看数据.
右边的事务并没有提交,在同一个时间段内,读取同一个数据有不同的结果,读取到了不同的值,这种现象叫做不可重复读(non reapeatable read).
事务之间互不影响.
可以看出两个事务之间并没有影响到彼此.
一般的数据库在可重复读提交时,屏蔽不了另一个事务的insert数据的影响.就是该事务insert数据,另一个事务可以看到insert之后的数据,尽管未提交,其他情况不会造成影响,这种情况为欢读情况.Mysql很好的解决了这个问题.
对所有操作全部加锁,进行串行化.
其中隔离级别越严格,安全性越高,但数据库的并发性能也就越低,往往需要在两者之间找一个平衡点。 不可重复读的重点是修改和删除:同样的条件, 你读取过的数据,再次读取出来发现值不一样了幻读的重点在于新增:同样的条件, 第1次和第2次读出来的记录数不一样说明: mysql 默认的隔离级别是可重复读,一般情况下不要修改上面的例子可以看出,事务也有长短事务这样的概念。事务间互相影响,指的是事务在并行执行的时候,即都没有commit的时候,影响会比较大。
其中可重复读Mysql数据库不会造成幻读现象.
脏读:读未提交时,另一个事务读到一个事务为提交的数据.
不可重复读:已提交读时,一个事务访问同一个数据,得出不同的结果.
幻读:可重复读时,读到另一个事务insert的数据.
事务执行的结果,必须使数据库从一个一致性状态,变到另一个一致性状态。当数据库只包含事务 成功提交的结果时,数据库处于一致性状态。如果系统运行发生中断,某个事务尚未完成而被迫中 断,而改未完成的事务对数据库所做的修改已被写入数据库,此时数据库就处于一种不正确(不一 致)的状态。因此一致性是通过原子性来保证的。 其实一致性和用户的业务逻辑强相关,一般MySQL提供技术支持,但是一致性还是要用户业务逻辑 做支撑,也就是,一致性,是由用户决定的。
而技术上,通过AID保证C.