事务的概念及使用

事务

       transaction,一组原子性的 SQL 查询,或者说是一个独立的工作单元。如果能够成功执行这组查询的全部语句,就会执行这组查询;如果其中任何一条语句无法成功执行,那么这组查询的所有语句都不会执行。

       也就是说,事务内部的语句,要么全部执行成功,要么全部执行失败。

使用事务

  1. 开始标志:任何一条 DML 语句的执行
  2. 结束标志:
    • 提交:成功的结束,将所有的DML语句操作记录和底层硬盘文件中数据进行同步
    • 回滚:失败的结束:将所有 DML 语句操作记录全部清

MySQL 默认是自动提交

#开启事务

start transaction;

#结束事务

end transaction;

#提交事务

commit;

#保存回滚点

savepoint 回滚点名;

#回滚事务

rollback[ to 回滚点名];

#查看事务的提交方式

show variables like 'autocommit';

#启用和关闭自动提交模式

set autocommit=1;

set autocommit=0;

举例:转账业务

  1. 创建表并插入数据

drop table if exists account;

create table account

(

  id int primary key auto_increment,

  name varchar(20),

  money int

);

insert into account

  (name, money)

values

  ("lz", 20000),

  ("xz", 500);

  1. 自动提交和手动提交,再开一个 MySQL-Front 窗口查看数据变化

#执行语句,再打开一个 MySQL-Front窗口,查询是否有变化

update account set money=money-1000 where name="lz";

update account set money=money+1000 where name="xz";

select * from account;

#查看提交方式,改为手动提交

show variables like 'autocommit';

set autocommit=off;

#手动提交

commit;

四个特性

ACID:

  1. 原子性(atomicity):事务是最小工作单元,不可再分,事务的所有操作要么全部提交成功,要么全部失败回滚,不可能只执行其中的一部分操作。
  2. 一致性(consistency):数据库总是从一个一致的状态转换成另一个一致状态,不会因为某条语句失败而出现其他状态。
  3. 隔离性(isolation):通常来说,一个事务所做的修改在最终提交前,对其他事务是不可见的。
  4. 持久性(durability):事务一旦提交,其做的修改会持久的保存到数据库中。此时即使系统崩溃,修改的数据也不会丢失。

一个兼容 ACID 的数据库系统,需要做很多复杂但可能用户并没有觉察到的工作。 相比没有实现 ACID 的数据库,通常会需要更强的 CPU 处理能力、更大的内存和更多的磁盘空间。

并行事务带来的问题

数据一致性问题:

  1. 脏读(dirty read):一个事务读到另一个事务未提交的数据就叫做脏读。一个事务对一条记录做修改,在这个事务提交前是有可能随时回滚的,这些数据就是脏数据。
  2. 不可重复读(non-repeatable read):在一个事务内多次读取同一条记录,前后结果不一样就叫做不可重复读。事务 A 多次查询同一行数据,在多次查询中间,事务 B 对该行数据进行了修改,事务 A 多次查询同一行的数据就会不一致。
  3. 幻读(phantom read):在一个事务内按相同条件多次查询,前后结果集的数量不同就叫做幻读。事务 A 按 id>5 的条件进行多次查询,在多次查询中间,事务 B 插入了一条 id 为6的数据,事务 A 多次查询的结果集数量就会不同。

影响:

  1. 脏读:读到其他事务未提交的数据
  2. 不可重复读:前后读取数据不一致
  3. 幻读:前后读取的结果集数量不同

隔离级别

在 SQL 标准中定义了四种隔离级别, 每一种级别都规定了一个事务中所做的修改,哪些在事务内和事务间是可见的,哪些是不可见的。较低级别的隔离通常可以执行更高的并发, 系统的开销也更低。

  1. READ UNCOMMITTED(未提交读):事务中的修改,没有提交也能被其他事务看到。这个级别会导致很多问题,性能也没有好太多,一般很少使用。
  2. READ COMMITTED(提交读):事务中的修改,提交后才能被其他事务看到。有时也叫不可重复读,因为两次执行同样的查询,可能得到不同的结果。
  3. REPEATABLE READ(可重复读):同一事务中多次读取同样记录的结果是一致的。该级别无法解决幻读问题。该级别是 MySQL 的默认隔离级别,并且 MySQL 在该级别就可以很大程度解决幻读问题。
  4. SERIALIZABLE(可串行化):强制事务串行执行,避免幻读问题。该级别会在读取的每一行数据上都加锁,可能导致大量的超时和锁争用的问题。实际很少用这个隔离级别,只有在非常需要确保数据的一致性而且可以接受没有并发的情况下,才考虑采用该级别。

查看隔离级别:

#查看会话级的当前隔离级别:(会话级只对当前窗口有效)

select  @@tx_isolation;

select @@session.tx_isolation;

#查看全局级的当前隔离级别:

select @@global.tx_isolation;

设置隔离级别:

  1. 方法1:my.ini 文件中的 [mysqld] 下面添加transaction-isolation=隔离级别
  2. 方法2:通过命令

#设置全局或当前会话范围

set global transaction isolation level 隔离级别;

set session transaction isolation level 隔离级别;

不同隔离级别下a1、a2、a3的值为多少?

  1. 未提交读:2、2、2
  2. 提交读:1、2、2
  3. 可重复读:1、1、2
  4. 串行化:1、1、2

实现隔离级别的两种方法:

  1. 加锁:读数据前对其加锁,阻止其他事务对数据修改
  2. 快照:读取数据的快照(之前的版本)实现,例如,可重复读级别在整个事务期间都读取事务开始时的快照去解决不可重复读问题。

你可能感兴趣的:(数据库MySQL知识储备,android)