什么是事务
事务就是【一组原子性的SQL查询】,或者说一个独立的工作单元。如果数据库引擎能够成功地对数据库应用该组查询的全部语句,那么就执行该组查询。
如果其中有任何一条语句因为崩溃或其他原因无法执行,那么所有的语句都不会执行。也就是说,事务内的语句,要么全部执行成功,要么全部执行失败。
事务控制语法
BEGIN 或 START TRANSACTION 显式地开启一个事务;
COMMIT / COMMIT WORK二者是等价的。提交事务,并使已对数据库进行的所有修改成为永久性的;
ROLLBACK / ROLLBACK WORK。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;
SAVEPOINT identifier 在事务中创建一个保存点,一个事务中可以有多个 SAVEPOINT;
RELEASE SAVEPOINT identifier 删除一个事务的保存点;
ROLLBACK TO identifier 把事务回滚到标记点;
SET TRANSACTION 用来设置事务的隔离级别。InnoDB 存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 和 SERIALIZABLE
事务的ACID特性
- 原子性(atomicity)
一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作。 - 一致性(consistency)
数据库总是从一个一致性的状态转换到另外一个一致性的状态。在前面的例子中,一致性确保了,即使在执行第三、四条语句之间时系统崩溃,CMBC账户中也不会损失100万,不然lemon要哭死,因为事务最终没有提交,所以事务中所做的修改也不会保存到数据库中。 - 隔离性(isolation)
通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的。在前面的例子中,当执行完第三条语句、第四条语句还未开始时,此时如果有其他人准备给lemon的CMBC账户存钱,那他看到的CMBC账户里还是有100万的。 - 持久性(durability)
一旦事务提交,则其所做的修改就会永久保存到数据库中。此时即使系统崩溃,修改的数据也不会丢失。持久性是个有点模糊的概念,因为实际上持久性也分很多不同的级别。有些持久性策略能够提供非常强的安全保障,而有些则未必。而且「不可能有能做到100%的持久性保证的策略」否则还需要备份做什么。
什么是脏读、不可重复读、幻读
脏读
在事务A修改数据之后提交数据之前,这时另一个事务B来读取数据,如果不加控制,
事务B读取到A修改过数据,之后A又对数据做了修改再提交,则B读到的数据是脏数据,此过程称为脏读Dirty Read。
时间 | 事务A | 事务B |
---|---|---|
T1 | START TRANSACTION | START TRANSACTION |
T2 | 查询CMBC账户余额100万 | |
T3 | 工资入账100万,CMBC账户余额200万 | |
T4 | 查询到CMBC账户余额200万(脏读) | |
T5 | 工资发错,撤回100万,账户余额100万 | |
T6 | 存入50万理财金,账户余额修改为250万 | |
T7 | COMMIT | |
T8 | COMMIT |
不可重复度
一个事务内在读取某些数据后的某个时间,再次读取以前读过的数据,却发现其读出的数据已经发生了变更、或者某些记录已经被删除了。
时间 | 事务A | 事务B |
---|---|---|
T1 | START TRANSACTION | START TRANSACTION |
T2 | 查询CMBC账户余额100万 | |
T3 | 查询到CMBC账户余额100万 | |
T4 | 存入50万理财金,账户余额修改为150万 | |
T5 | COMMIT提交事务 | |
T6 | 查询CMBC账户余额150万(不可重复读) | |
T7 | ||
T8 | COMMIT |
幻读
事务A在按查询条件读取某个范围的记录时,事务B又在该范围内插入了新的满足条件的记录,当事务A再次按条件查询记录时,会产生新的满足条件的记录(幻行 Phantom Row)
时间 | 事务A | 事务B |
---|---|---|
T1 | START TRANSACTION | START TRANSACTION |
T2 | 查询CMBC账户今天交易详情,返回2条交易记录 | |
T3 | 存入50万理财金,交易记录加1 | |
T4 | ||
T5 | COMMIT提交事务 | |
T6 | 查询CMBC账户今天交易详情,返回3条记录(幻读) | |
T7 | ||
T8 | COMMIT |
不可重复读与幻读区别?
- 不可重复读的重点是修改:在同一事务中,同样的条件,第一次读的数据和第二次读的【数据不一样】。(因为中间有其他事务提交了修改)
- 幻读的重点在于新增或者删除:在同一事务中,同样的条件,第一次和第二次读出来的【记录数不一样】。(因为中间有其他事务提交了插入/删除)
四个隔离级别
事务隔离级别 | 特点 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|---|
Read Uncommited | 所有事务都可以看到其他事务未提交的修改 | YES | YES | YES |
Read Commited | 一个事务只能看到其他已经提交的事务所做的变更 | NO | YES | YES |
Repeatable Read | 确保同一事务的多个实例在并发读取数据时会看到相同的数据行 | NO | NO | YES |
Serializable | 最高的隔离级别,完全串行化读,事务串行执行,读取每一行数据都加锁,会导致大量的超时和锁争用问题. | NO | NO | NO |
MySQL中哪些存储引擎支持事务
MySQL中InnoDB和NDB Cluster存储引擎提供了事务处理能力,以及其他支持事务的第三引擎。
自动提交
MySQL默认采用自动提交AUTOCOMMIT
模式。也就是说,如果不是显式地开始一个事务,则每个查询都被当作一个事务执行提交操作。
对于MyISAM或者内存表示这些事务型的表,修改AUTOCOMMIT
不会有任何影响。对这类表来说,没有COMMIT
或者ROLLBACK
的概念,也可以说是相当于一直处于AUTOCOMMIT
启用的模式
MySQL存储引擎类型有哪些
最常用的存储引擎是InnoDB引擎和MyISAM存储引擎,InnoDB是MySQL的默认事务引擎。
查看数据库当前支持的引擎:
show table status from 'your_db_name' where name='your_table_name';
查询结果表中的'Engine'字段指示存储引擎类型。
InnoDB存储引擎的特点和应用场景
InnoDB是MySQL的默认【事务引擎】,被设置用来处理大量短期(short-lived)事务,短期事务大部分情况是正常提交的,很少会回滚。
参考MySQL官方手册 https://dev.mysql.com/doc/refman/5.7/en/innodb-transaction-model.html