1.介绍
事务就是一组
DML
语句组成,这些语句在逻辑上存在相关性,这一组
DML
语句要么全部成功,要么全部失败,是一个整体。MySQL
提供一种机制,保证我们达到这样的效果。
一个
MySQL
数据库,可不止你一个事务在运行,同一时刻,甚至有大量的请求被包装成事务,
在向
MySQL
服务器发起事务处理请求。而每条事务至少一条
SQL
,最多很多
SQL
,
这样如果大家都访问同样的表数据,在不加保护的情况,就绝对会出现问题。
一个完整的事务,绝对不是简单的 sql 集合,还需要满足如下四个属性:
上面四个属性,可以简称为 ACID 。 当我们使用事务时,要么提交,要么回滚。因此事务本质上是为了应用层服务的。而不是伴随着数据库系统天生就有的。
2.事务的版本支持
在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务, MyISAM 不支持。
3.事务的提交方式
事务的提交方式常见的有两种:
查看事务提交方式
show variables like
'autocommit'
;
用 SET 来改变 MySQL 的自动提交模式:
SET AUTOCOMMIT=0; #SET AUTOCOMMIT=0 禁止自动提交
SET AUTOCOMMIT
=
1
;
#SET AUTOCOMMIT=1
开启自动提交
4.事务的操作
- 只要输入begin或者start transaction,事务便必须要通过commit提交,才会持久化,与是否设置set autocommit无关。
- 事务可以手动回滚,同时,当操作异常,MySQL会自动回滚。
- 对于 InnoDB 每一条 SQL 语言都默认封装成事务,自动提交。(select有特殊情况,因为 MySQL 有MVCC )。
- 从上面的例子,我们能看到事务本身的原子性(回滚),持久性(commit)。
savepoint save1; -- 创建一个保存点save1
当插入或删除一个数据后,想放弃这次的操作可以回滚到保存点save1
rollback to save1;
-- 回滚到save1
事务操作注意事项
- 如果没有设置保存点,也可以回滚,只能回滚到事务的开始。直接使用 rollback(前提是事务还没有提交)。
- 如果一个事务被提交了(commit),则不可以回退(rollback)。
- 可以选择回退到哪个保存点。
- InnoDB 支持事务, MyISAM 不支持事务。
- 开始事务可以使 start transaction 或者 begin。
5.事务隔离级别
5.1 如何理解隔离性?
隔离级别
5.1.1 读未提交
读未提交【
Read Uncommitted
】
: 在该隔离级别,所有的事务都可以看到其他事务没有提交的执行结果。(实际生产中不可能使用这种隔离级别的),但是相当于没有任何隔离性,也会有很多并发问题,如脏读,幻读,不可重复读等。
--几乎没有加锁,虽然效率高,但是问题太多,严重不建议采用。
--一个事务在执行中,读到另一个执行中事务的更新(或其他操作)但是未commit的数据,这种现象叫做脏读(dirty read)
5.1.2 读提交
读提交【
Read Committed
】
:该隔离级别是大多数数据库的默认的隔离级别(不是
MySQL
默认的)。它满足了隔离的简单定义:
一个事务只能看到其他的已经提交的事务所做的改变。这种隔离级别会引起不可重复读,即一个事务执行时,如果多次 select
, 可能得到不同的结果。
同一个事务内,同样的读取,在不同的时间段
(
依旧还在事务操作中!)
,读取到了不同的值,这种现象叫做不可重复读
(non reapeatable read)。
5.1.3 可重复读
可重复读【
Repeatable Read
】
: 这是
MySQL
默认的隔离级别,它确保同一个事务,在执行中,多次读取操作数据时,会看到同样的数据行。但是会有幻读问题。
insert的数据在可重复读情况被读取出来,导致多次查找时,会多查找出来新的记录,就如同产生了幻觉。这种现象,叫做幻读(phantom read)。
5.1.4 串行化
串行化【
Serializable
】
:
这是事务的最高隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决了幻读的问题。它在每个读的数据行上面加上共享锁,。但是可能会导致超时和锁竞争。(这种隔离级别太极端,实际生产基本不使用)
--对所有操作全部加锁,进行串行化,不会有问题,但是只要串行化,效率很低,几乎完全不会被采用。
5.2 总结
- 隔离级别越严格,安全性越高,但数据库的并发性能也就越低,往往需要在两者之间找一个平衡点。
- 不可重复读的重点是修改和删除:同样的条件, 你读取过的数据,再次读取出来发现值不一样了 幻读的重点在于新增:同样的条件, 第1次和第2次读出来的记录数不一样。
- mysql 默认的隔离级别是可重复读,一般情况下不要修改。
set global transaction isolation level 隔离级别 --设置全局隔离级别的SQL命令
6.一致性