事务是由一个或多个sql语句组成一个最小的不可再分的工作单元。里面的内容要么都执行成功,要么都不成功。
原子性(atomicity)
一致性(consistency)
隔离性(isolation)
持久性(durability)
show engines
命令可以查看mysql存储引擎支持事务的情况。
在mysql中,只有innodb是支持事务的。
START TRANSACTION或BEGIN能显式的开启一个事务。
BEGIN;
# 或者
START TRANSACTION;
START TRANSACTION相较于BEGIN可以在后边跟随几个修饰符。
READ ONLY
: 表示当前事务是一个只读事务READ WRITE
: 当前事务是一个读写事务WITH CONSISTENT SNAPSHOT
启动一致性读(在开启事务的时候就生成Readview)事务的相关操作如下:
COMMIT;
ROLLBACK;
ROLLBACK TO [SAVEPOINT];
SAVEPOINT 保存点名称;
RELEASE SAVEPOINT 保存点名称; #删除保存点
如果不显式使用START TRANSACTION或BEGIN开启一个事务,那么每一条语句是一个独立的事务,这种特性叫做事务的自动提交。
如果想关闭自动提交,有两种方法:
autocommit
的值设置为off注意事项——隐式提交
SQL在并发事务执行过程中可能存在以下问题:
脏写、脏读、不可重复读、幻读
mysql提供四种隔离级别,用来解决并发问题:
READ UNCOMMITTED
: 读未提交,在该隔离级别下,所有事务都可以看到其他事务未提交的数据。不能避免脏读、不可重复读、幻读。READ COMMITTED
: 读已提交,一个事务只能看到已经提交的事务。可以避免脏读,不能避免不可重复读、幻读。REPEATABLE READ
: 可重复读,事务A在读到记录后,其他事务对该记录修改后,A事务读到的还是原来的内容。可以避免脏读、不可重复读,不能避免幻读。这是mysql默认的隔离级别。SERIALIZABLE
: 可串行化,所有事务串行执行。show variables like 'tx_isolation'; # 查看隔离级别,mysql5.7.20之前
show variables like 'transaction_isolation' # 查看隔离级别,mysql5.7.20之后
select @@transaction_isolation
SET [GLOBAL|SESSION] TRANSACTION_ISOLATION = '隔离级别'
undo log是事务原子性的保证,在事务更新数据时需要先写入undo log。
回滚数据
用户对undo日志可能有误解:undo用于将数据库物理地恢复到执行语句或事务之前的样子。但事实并非如此。undo是逻辑日志,因此只是将数据库逻辑地恢复到原来的样子。所有修改都被逻辑地取消了,但是数据结构和页本身在回滚之后可能大不相同。
这是因为在多用户并发系统中,可能会有数十、数百甚至数千个并发事务。数据库的主要任务就是协调对数据记录的并发访问。比如,一个事务在修改当前一个页中某几条记录,同时还有别的事务在对同一个页中另几条记录进行修改。因此,不能将一个页回滚到事务开始的样子,因为这样会影响其他事务正在进行的工作。
MVCC
undo的另一个作用是MVCC,即在InnoDB存储引擎中MNCc的实现是通过undo来完成。当用户读取一行记录时,若该记录已经被其他事务占用,当前事务可以通过undo读取之前的行版本信息,以此实现非锁定读取。
InnoDB对undo log的管理采用段的方式,也就是回滚段(rollback segment)
,每个回滚段记录类1024个undo log segment
。
innodb_undo_directory : 设置文件所在路径。
innodb_undo_tablespaces : 设置文件数量.
undo log类型分为:
因为insert操作的记录,只对事务本身可见,对其他事务不可见。故该undo log可以在事务提交后直接删除,不需要进行purge操作
该undo log可能需要提供MVCC机制,因此不能在事务提交时就进行删除。提交时放入undo log链表,等待purge线程进行最后的删除
redo log称为重做日志,提供再写入操作,恢复提交事务修改页操作,用来保证事务的持久性。
redo log记录的是物理级别上页的修改操作。
InnoDB的事务存储引擎,其通过Force Log at Commit机制实现事务的持久性,即当事务提交时,先将redo log buffer写入到redo log file进行持久化,待事务的commit操作完成后才算完成。这种做法也被称为Write-Ahead Log(预先日志持久化),在持久化一个数据页之前,先将内存中相应的日志持久化。
通过调整innodb_flush_log_at_trx_commit
,支持不同的刷盘策略:
0
: 表示每次事务提交时不进行刷盘操作,由系统后台线程每隔1s进行一次同步。1
: 默认为1,表示每次事务提交时都将进行同步,刷盘操作2
: 表示每次事务提交时都只写到oage cache,不进行同步,由os自己决定什么时候同步到磁盘。