事务
一个事务是由一条或多条对数据库操作的sql语句所组成的一个不可分割的单元,只有当事务中的所有操作都正常执行完了,整个事务才会被提交给数据库;如果有部分事务处理失败,那么事务就回退到最初的状态。
- 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。
- 事务处理可以用来维护数据库的完整性,保证成批的 SQL语句要么全部执行,要么全部不执行。
- 事务用来管理 insert,update,delete 语句,相关操作命令如下:
select @@autocommit; //查看MySql是否已经关闭自动提交 0 表示手动提交事务 1表示自动提交事务
set @@autocommit = 0;//设置MySql关闭自动提交
begin;start transaction;//标记事务的开始 可省略
commit;rollback;//标记事务的结束
savepoint point1;//设置一个名为point1的标记点
rollback to point1;//事务回滚到保存点point1的位置
事务的四大特性(ACID)
(1)事务的原子性(Atomicity)
事务是一个不可分割的整体,事务必须具有原子性,即当数据修改时,要么全部执行,要么全部执行,不支持部分修改。
原子性通过Mysqld的undo log日志(回滚日志)实现,提供回滚操作
开启事务会开启undo log日志,如果发现sql语句中有执行错误的sql,那么直接调用rollback退回,如果没有发现任何执行错误的sql,那么执行的commit这个时候才会对数据造成持久性伤害。
在sql语句执行的时候会记录一条和你要执行的sql作用相反的sql语句。当执行insert语句时,undo log中会记录对应的delete语句,当执行delete语句,记录对应的insert语句,当你执行rollback时可以读取undo log日志然后回滚数据;当我们执行commit这个时候就会对undo log日志进行数据清空,此时不能在回滚
(2)事务的一致性(Consistency)
一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。
(3)事务的隔离性(Isolation)
隔离性的实现原理 :mysql锁机制+MVCC机制
当多个事务并发执行时,为了保证数据的安全性,将一个事务内部的操作与其他事务的操作隔离起来,不被其他正在执行的事务所看到。隔离性使每个事务的更新在被它提交前,对其他事务不可见。
- MVCC机制:
多版本并发机制,MVCC机制就是尽量不去使用这些锁 一旦这些锁加上之后事务与事务之间就变成了完全的串行执行(一个执行完另一个才执行),在隔离级别中串行化就是这样做的。MVCC的实现,是通过保存数据在某一个时间点的快照作为每个事务操作数据的并且记录为一个版本,每一个事务只操作自己版本下的数据。(每一个事务都有一个数据的副本,事务操作的是自己副本下的数据)
事务的隔离级别:
-
未提交读:read uncommitted
未提交读即在一个客户端开启事务A,设置隔离级别为read uncommitted,进行了数据的更新操作,但此时事务A未提交(committed),在另一个客户端进行事务B查询可以查询到更新后的数据。当事务A更新后,事务B查询读取到A事务未提交的数据,此时事务A回滚,则事务B读取到的数据就是无效的脏数据(脏读) -
已提交读:read committed
已提交读如果在一个客户端开启事务A,设置隔离级别为read committed,进行数据的更新操作,事务A未提交的情况下,在另一个客户端进行事务B查询时查询到的仍然是更新操作前的数据,解决了脏读的问题。事务A提交后,事务B进行查询时查询到的是更新后的数据。
但是出现了不可重复读的现象,即事务B 两次查询结果不同。 -
可重复读:repeatable read
可重复读如果在一个客户端开启事务A,设置隔离级别为repeatable read,进行数据的更新操作,事务A未提交的情况下,在另一个客户端进行事务B查询时查询到的仍然是更新操作前的数据,解决了脏读的问题。事务A提交后,事务B进行查询时查询到的是更新操作前的数据(两次查询结果一致,避免了不可重复读的现象),事务B提交后,再次查询,此时的查询结果才是更新后的数据。 -
串行化:serializable
在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了虚读/幻读的现象。
MySQL的默认隔离级别就是Repeatable read。
MySQL数据库的四种隔离级别下:
① Serializable (串行化):可避免脏读、不可重复读、幻读的发生。
② Repeatable read (可重复读):可避免脏读、不可重复读的发生。
③ Read committed (读已提交):可避免脏读的发生。
④ Read uncommitted (读未提交):最低级别,任何情况都无法保证。
设置事务的隔离级别(设置数据库的隔离级别在开启事务之前)
select @@tx_isolation;//查询默认隔离级别
set session transaction isolation level + 隔离级别;//设置事务的隔离级别
(4)事务的持久性(Durability)
事务的持久性通过redo log日志实现
redo log日志:当数据进行修改时,不仅修改Buffer Pool中的数据,还会在redo log记录这次操作;当事务提交时,会用fsync接口丢redo log进行刷盘,如果Mysql宕机,重启时可以读取redo log中的数据,对数据进行恢复。
事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。