SQL-事务

1. 事务

  • 事务就是一次处理的基本单元

1.1 事务的特性-ACID

  • Atomicity 原子性,基本单位,说明不可分割,要么全部成功,要么全部失败
  • Consistency 一致性:数据库进行事务操作后,会由一种状态变为另一种状态
  • Isolation:隔离性:每个事务都是彼此独立的,不会受到其他事务的执行影响
  • Durability:持久性:通过事务日志保证。

1.2 如何对事务进行控制

  • START TRANSACTION或BEGIN
  • COMMIT:提交事务。事务提交后,对数据库的修改是永久性的
  • ROLLBACK
  • SAVEPOINT
  • RELEASE SAVEPOINT
  • SET TRANSACTION:设置事务的隔离级别

事务的分类

  • 隐式事务:实际上就是自动提交。MYSQL默认情况下就是隐式事务
  • 显示事务

1.4 为什么执行COMMITROLLBACK有时会成功,有时会失败

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默认,解决脏读和不可重复读
  • 串行化:解决所有,但是牺牲了系统的并发性。将事务串行化,在一个队列中按照顺序执行
posted @ 2020-11-15 23:28  coderrrrrrr  阅读(88)  评论(0)    收藏  举报