SQL-事务
1. 事务
- 事务就是一次处理的基本单元
1.1 事务的特性-ACID
- Atomicity 原子性,基本单位,说明不可分割,要么全部成功,要么全部失败
- Consistency 一致性:数据库进行事务操作后,会由一种状态变为另一种状态
- Isolation:隔离性:每个事务都是彼此独立的,不会受到其他事务的执行影响
- Durability:持久性:通过事务日志保证。
1.2 如何对事务进行控制
- START TRANSACTION或BEGIN
- COMMIT:提交事务。事务提交后,对数据库的修改是永久性的
- ROLLBACK
- SAVEPOINT
- RELEASE SAVEPOINT
- SET TRANSACTION:设置事务的隔离级别
事务的分类
- 隐式事务:实际上就是自动提交。MYSQL默认情况下就是隐式事务
- 显示事务
1.4 为什么执行COMMIT、ROLLBACK有时会成功,有时会失败
CREATE TABLE test(name varchar(255), PRIMARY KEY (name)) ENGINE=InnoDB;
BEGIN;
INSERT INTO test SELECT '关羽';
COMMIT;
BEGIN;
INSERT INTO test SELECT '张飞';
INSERT INTO test SELECT '张飞';
ROLLBACK;
SELECT * FROM test;
执行结果为插入一个关羽,第二个事务进行了回滚
CREATE TABLE test(name varchar(255), PRIMARY KEY (name)) ENGINE=InnoDB;
BEGIN;
INSERT INTO test SELECT '关羽';
COMMIT;
INSERT INTO test SELECT '张飞';
INSERT INTO test SELECT '张飞';
ROLLBACK;
SELECT * FROM test;
此时查询结果为关羽、张飞:
- 第一次事务插入关羽
- 因为是隐式事务,所以第二次插入张飞已经是一次事务了。第三次插入张飞报错回滚
- 而开头的例子中,两次插入张飞是在一次事务中,发生了异常回滚
CREATE TABLE test(name varchar(255), PRIMARY KEY (name)) ENGINE=InnoDB;
SET @@completion_type = 1;
BEGIN;
INSERT INTO test SELECT '关羽';
COMMIT;
INSERT INTO test SELECT '张飞';
INSERT INTO test SELECT '张飞';
ROLLBACK;
SELECT * FROM test;
-
completion_type
- 0:默认情况。执行commit会提交事务;在执行下一次事务时,需要START TRANSACTION或BEGIN来开启
- 1:提交事务时,相当于开启了COMIT AND CHAIN;也就是开启了链式事务,当我们提交了事务之后,会开启一个相同隔离级别的事务
- 2:这种情况下 COMMIT=COMMIT AND RELEASE,也就是当我们提交后,会自动与服务器断开连接
-
当我们设置 autocommit=0 时,不论是否采用 START TRANSACTION 或者 BEGIN 的方式来开启事务,都需要用 COMMIT 进行提交,让事务生效,使用 ROLLBACK 对事务进行回滚。
-
当我们设置 autocommit=1 时,每条 SQL 语句都会自动进行提交。--隐式
不过这时,如果你采用 START TRANSACTION 或者 BEGIN 的方式来显式地开启事务,那么这个事务只有在 COMMIT 时才会生效,在 ROLLBACK 时才会回滚。
2. 事务隔离
- 隔离性可以防止数据库在并发处理时出现数据不一致的情况
- 理论上,可以设置串行化的方式执行吗,每一个事务,实际上难以应对高并发
2.1 三种异常
- 脏读
- 读到了其他事务还没有提交的数据
- A往表中加数据,还未提交事务
- 此时B去查看数据库,会看到A还未提交事务的数据
- 不可重复读
- 是同一条记录,两次读取的结果不同。
- A读数据
- B修改数据
- A再读数据
- 幻读
- 事务 A 根据条件查询得到了 N 条数据,但此时事务 B 更改或者增加了 M 条符合事务 A 查询条件的数据,这样当事务 A 再次进行查询的时候发现会有 N+M 条数据,产生了幻读。
2.2 四种隔离级别
- 读未提交:就是可以读取未提交的数据;不解决上述问题
- 读已提交:只能读取提交的内容,所以只能避免脏读
- 所以如果要避免不可重读和幻读,需要编写加锁的SQL
- 可重复读:MySQL默认,解决脏读和不可重复读
- 串行化:解决所有,但是牺牲了系统的并发性。将事务串行化,在一个队列中按照顺序执行
浙公网安备 33010602011771号