MySQL事务
1、MYSQL的概念
1、什么是事务,有哪些特性?
什么是事务?
事务(TRANSACTION)是一个不可分割的逻辑单元,包含了一组数据库操作命令,并且把所有的命令作为一个整体向系统提交,要么都执行、要么都不执行。 举例:确保转账的过程作为一个整体,要么同时成功,要么同时失败。
事务特性?
事务必须具备以下四个属性,简称ACID 属性 (1)原子性(Atomicity):事务是一个完整的操作,事务的各步操作是不可分的(原子的),要么都执行,要么都不执行。 (2)一致性(Consistency):当事务完成时,数据必须处于一致状态。 转账前和转账后的总金额不变 (zs1000 ,li1000 转账前 2000 转账后2000) (3)隔离性(Isolation): 并发事务之间彼此隔离、独立,它不应以任何方式依赖于或影响其他事务。 (4)持久性(Durability): 事务完成后,它对数据库的修改被永久保存。
2、MySQL 开启一个事务?
1、开始事物
BEGIN / START TRANSACTION;
2、提交事物
COMMIT ;
3、回滚(撤销)事物
ROLLBACK ;
3、显示事务与隐士事务?
3.1 显示事务
1、准备表
CREATE TABLE account( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20) UNIQUE NOT NULL, balance INT ); INSERT INTO account VALUES(NULL,'zs',1000); INSERT INTO account VALUES(NULL,'lisi',0);
2、开启事物,执行转账操作,不提交事物
BEGIN; /*--转账:张三的账户减少500元,李四的账户增加500元--*/ UPDATE account SET balance=balance-500 WHERE `name`='zs'; UPDATE account SET balance=balance+500 WHERE NAME='lisi'; COMMIT;
3、打开新的会话,查询,数据没有变化
4、提交事务,再次查询,转账完成。
6、事务回滚
BEGIN; DELETE FROM account WHERE NAME='zs'; ROLLBACK;
7、设置回滚点
在事务中创建保存点,方便后续针对保存点进行回滚。一个事务中可以存在多个保存点。 BEGIN; DELETE FROM account WHERE NAME='zs'; SAVEPOINT my_rollback_1; -- 回滚到这里之前 DELETE FROM account WHERE NAME='lisi'; ROLLBACK TO my_rollback_1; COMMIT;
对于InnoDB引擎,它使用了撤销日志(undo log)和重做日志(redo log)来实现事务回滚。在执行修改数据的SQL语句时,InnoDB会先将修改前的数据记录到撤销日志中,然后再将修改的操作记录到重做日志中。如果需要回滚事务,InnoDB会根据撤销日志将数据恢复到修改前的状态。
undo log原理
undo log是把所有没有COMMIT的事务回滚到事务开始前的状态,系统崩溃时,可能有些事务还没有COMMIT,在系统恢复时,这些没有COMMIT的事务就需要借助undo log来进行回滚。
使用undo log时事务执行顺序
1. 记录START T 2. 记录需要修改的记录的旧值(要求持久化) 3. 根据事务的需要更新数据库(要求持久化) 4. 记录COMMIT T
使用undo log进行宕机回滚
1. 扫描日志,找出所有已经START,还没有COMMIT的事务。 2. 针对所有未COMMIT的日志,根据undo log来进行回滚。
3.2 隐士事务
(1)在MySQL中执行DML语句,会自动提交事物。
delete from account where name='zs';
(2)MySQL中有一个系统变量 autocommit
, 可以查看是否开启自动提交事物。
SHOW VARIABLES LIKE 'autocommit';
(3)把系统变量autocommit
的值设置为 OFF
,则会关闭自动提交。
SET autocommit = OFF; #或SET autocommit = 0;
(4)再次执行DML语句,发现不会自动提交。
insert into account values(null,'zs',1000);
(5)此时必须显示的提交事物才能生效
commit;
4、事物的隔离级别
4.1 四种隔离级别 (解决事务的并发问题)
MySQL 中事务的隔离级别一共分为四种,分别如下:
-
序列化(SERIALIZABLE)
-
可重复读(REPEATABLE READ)
-
读已提交(READ COMMITTED)
-
读未提交(READ UNCOMMITTED)
读未提交(READ UNCOMMITED)->读已提交(READ COMMITTED)->可重复读(REPEATABLE READ)->序列化(SERIALIZABLE)。隔离级别依次增强,但是导致的问题是并发能力的减弱。
隔离级别 | 脏读 | 不可重复读 | 幻读 | 概念 |
---|---|---|---|---|
READ UNCOMMITED | √ | √ | √ | 事务能够看到其他事务没有提交的修改,当另一个事务又回滚了修改后的情况,又被称为脏读dirty read |
READ COMMITTED | × | √ | √ | 事务能够看到其他事务提交后的修改,这时会出现一个事务内两次读取数据可能因为其他事务提交的修改导致不一致的情况,称为不可重复读 |
REPEATABLE READ | × | × | √ | 事务在两次读取时读取到的数据的状态是一致的 |
SERIALIZABLE | × | × | × | 可重复读中可能出现第二次读读到第一次没有读到的数据,也就是被其他事务插入的数据,这种情况称为幻读phantom read, 该级别中不能出现幻读 |
大多数数据库系统的默认隔离级别都是READ COMMITTED(但MySQL不是),InnoDB存储引擎默认隔离级别REPEATABLE READ,通过多版本并发控制(MVCC,Multiversion Concurrency Control)解决了幻读的问题。
四种不同的隔离级别含义分别如下:
(1)SERIALIZABLE 序列化
如果隔离级别为序列化,则事物是顺序地执行,这种隔离级别提供了事务之间最大限度的隔离。 数据安全、效率低
(2)REPEATABLE READ 可重复读
事物如果是可重复读隔离级别,则在当前事务处理期间,所发生的数据变化不会被其它事物看到。也就是说,如果用户在另外一个事务中执行同条 SELECT 语句数次,结果总是相同的。(因为正在执行的事务所产生的数据变化不能被外部看到)。
(3)READ COMMITTED 读已提交
READ COMMITTED 隔离级别的安全性比 REPEATABLE READ 隔离级别的安全性要差。处于 READ COMMI