事务
事务是由一组SQL语句组成的一个执行单元,该执行单元要么全部执行或全部不执行
事务四大特质(ACID)
原子性(Atomicity):指事务包含的所有操作(sql)要么全部成功,要么全部失败回滚。事务是最小单位,不可再分。
- 回滚通过undo log实现,回滚行记录到某个特定版本
- undo log 记录的是
逻辑操作
日志(如对某行数据进行insert操作,那么undo log会记录一条与之相反的delete操作)
隔离性(Isolation):事务A和事务B之间具有隔离性,一个事务在最终提交之前,对其它事务不可见。
- 通过锁机制实现
持久性(Durability):一旦事务提交,其所做的修改永远保存在数据库中。即使系统发生崩溃,事务执行的结果也不能丢失。(内存的数据持久到硬盘文件中)
- 系统发生崩溃可以通过重做日志(Redo log)进行恢复,从而实现持久性,是数据页的
物理修改
(页号、偏移量)。 - 假设内存1s会一直做刷盘操作,若当发生宕机时,内存会把内存中的数据写入Redo log中,机器恢复之后,磁盘会从Redo log中获取数据,完成数据恢复
- 系统发生崩溃可以通过重做日志(Redo log)进行恢复,从而实现持久性,是数据页的
一致性(Consistency):事务要求所有的DML语句操作的时候,必须保证同时成功或者同时失败。ACI为了一致性
比如上一个事务中执行了第二步时系统崩溃了,数据也不会出现bill的账户少了100块,但是tim的账户没变的情况。要么维持原装(全部回滚),要么bill少了100块同时tim多了100块,只有这两种一致性状态的
并发问题
当要同时执行多个事务时,这些事务访问数据库中相同的数据时,如果没有相应的事务隔离级别,就会引发各种并发问题:
曾经被问过一个问题:如果有人同时新增预约系统的数据,有没有相应的措施?其实是在考数据库的并发问题啊
脏读(未提交读)
如2个事务T1、T2,如果T1读取了已被T2更新过但没有提交的字段之后,若T2回滚,T1读取的内容是暂时且无效的不可重复读
如2个事务T1、T2,如果T1读取了一个字段,然后T2更新了该字段并提交之后,T1再次读同一个字段,值就不同了(重点是更新)
幻读
如2个事务T1T2,如果T1从数据表读了一个字段,然后T2在表中插入新的行,之后如果T1再读取同一个表,就会出现多了几行(重点是插入)
解决:在可重复读隔离级别下,使用 MVCC + Next-Key Locks解决
MySQL的事务隔离级别
MySQL支持4种事务隔离级别,Oracle支持2种(Read Commit,Serializable)
- READ UNCOMMITED(读未提交数据)
- READ COMMITED(读已提交的数据)
- REPETABLE READ(可重复读) MySQL默认 解决了不可重复读、幻影读的问题,使用 MVCC + Next-Key Locks实现
- SERIALIZABLE(串行化) 锁