数据库引入事务的主要目的
事务会把数据库从一种状态转换为另一种一致的状态,在提交工作时,可以确保要么所有修改都已经保存,要么都不保存。
ACID特性
原子性 atomicity
要么都成功,要么都失败。
一致性 consistency
事务执行前后,数据库的完整性约束没有破坏。(你的10张银行卡里共有100块,无论这10张银行卡之间怎么转账,也只有100块)
隔离性 isolation
一个事务的影响在事务提交前,其他事务都不可见。
持久性 durability
事务一旦提交,就是永久性的。
事务的实现
redo
事务通过重做(redo)日志文件和日志缓冲(InnoDB Log Buffer)实现。在写数据前,需要先写日志。这种实现方式称为预写日志方式(Write-Ahead Logging,WAL)
当开始一个事务时,会记录该事务的一个LSN(Log Sequence Number,日志序列号);
当事务执行时,会往InnoDB存储引擎的日志缓冲里插入事务日志;
事务提交是,必须将InnoDB存储引擎的日志缓冲写入磁盘。
通过预写日志的方式保证事务的完整性,会造成吸盘上存储的数据页和内存缓冲池中的页是不同步的。可以通过show engine innodb status;
查看当前磁盘和日志的差距。show engine innodb status; LOG Log sequence number 77292702 # 当前LSN Log flushed up to 77292702 # 刷新到重做日志文件的LSN Pages flushed up to 77292702 Last checkpoint at 77292702 # 刷新到磁盘的LSN 0 pending log writes, 0 pending chkp writes 8 log i/o's done, 0.00 log i/o's/second
undo
事务需要回滚,需要undo。undo与redo正好相反,对于数据库进行修改是,数据库不但会产生redo,还会产生一定量的undo。
redo存放在重做日志中,undo存放在数据库内部的一个特殊段(segment)中,称为undo段(undo segment),undue段位于共享表空间中。
undo用于将数据库逻辑的恢复到原来的样子,数据结构本身在回滚前后可能不是相同的。
事务常用控制语句
- begin
- commit
- rollback
事务的隔离级别
读未提交 read uncommitted
浏览访问
读已提交 read committed
游标稳定,生产上常用隔离级别
可重复度 repeatable read
InnoDB默认隔离级别,InnoDB在该级别下使用
next-key
锁的算法避免幻读的产生。序列化 serializable
InnoDB会对每个select操作自动添加
lock in share mode
,即共享锁。因为InnoDB在rr的隔离级别就可以避免幻读,所以serializable隔离级别主要用于分布式事务。
查看事务隔离级别
select @@tx_isolation\G;
select @@global.tx_isolation\G;
分布式事务
分布式事务由一个或多个资源管理器、一个事务管理器和一个应用程序组成。
分布式事务使用两段式提交two-phase commit
的方式。在第一个阶段,所有参与全局事务的节点都开始准备,告诉事务管理器他们准备好了。第二阶段,事务管理器告诉所有资源管理器执行rollback还是commit。如果任何节点显示不能提交,则所有节点都被告知需要回滚。
资源管理器
提供访问事务资源的方法。通常一个数据库就是一个资源管理器。
事务管理器
协调参与全局事务中的各个事务。需要合参与全局事务中的所有资源管理器进行通信。
应用程序
定义事务的边界,置顶全局事务中的操作。