MySQL 之 事务
1、事务概述
MySQL 事务主要用于处理操作量大,复杂度高的数据。比如说,在员工管理系统中,删除一个员工,既需要删除员工的基本资料,也要删除和该员工相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务。
- 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。
- 事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。
- 事务用来管理 insert,update,delete 语句
2、事务的ACID特性
一般来说,事务是必须满足4个条件(ACID)::原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。
- 原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
- 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
- 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
- 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
在 MySQL 命令行的默认设置下,事务都是自动提交的,即执行 SQL 语句后就会马上执行 COMMIT 操作。因此要显式地开启一个事务务须使用命令 BEGIN 或 START TRANSACTION,或者执行命令 SET AUTOCOMMIT=0,用来禁止使用当前会话的自动提交。
3、事务的隔离级别
脏数据:是事务回滚的结果,读取到另一个事务未提交的数据
不可重复读 :多次读取数据因修改不一致
侧重修改,锁数据解决
幻读:修改数据因插入操作个别未成功
侧重新增/删除 ,锁表解决
(1)、Read uncommitted(读未提交)
如果一个事务已经开始写数据,则另外一个事务不允许同时进行写操作,但允许其他事务读此行数据,该隔离级别可以通过“排他写锁”,但是不排斥读线程实现。这样就避免了更新丢失,却可能出现脏读,也就是说事务B读取到了事务A未提交的数据。
特点:解决了更新丢失,但还是可能会出现脏读
(2)、Read committed(读提交)
如果是一个读事务(线程),则允许其他事务读写,如果是写事务将会禁止其他事务访问该行数据,该隔离级别避免了脏读,但是可能出现不可重复读。事务A事先读取了数据,事务B紧接着更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。
特点:解决了更新丢失和脏读问题
(3)、Repeatable read(可重复读取)
可重复读取是指在一个事务内,多次读同一个数据,在这个事务还没结束时,其他事务不能访问该数据(包括了读写),这样就可以在同一个事务内两次读到的数据是一样的,因此称为是可重复读隔离级别,读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务(包括了读写),这样避免了不可重复读和脏读,但是有时可能会出现幻读。(读取数据的事务)可以通过“共享读镜”和“排他写锁”实现。
特点:解决了更新丢失、脏读、不可重复读、但是还会出现幻读
(4)、Serializable(可序化)
提供严格的事务隔离,它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行,如果仅仅通过“行级锁”是无法实现序列化的,必须通过其他机制保证新插入的数据不会被执行查询操作的事务访问到。序列化是最高的事务隔离级别,同时代价也是最高的,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻读。
特点:解决了更新丢失、脏读、不可重复读、幻读(虚读)
以上四种隔离级别最高的是Serializable级别,最低的是Read uncommitted级别,当然级别越高,执行效率就越低,像Serializeble这样的级别,就是以锁表的方式使得其他线程只能在锁外等待,所以平时选用何种隔离级别应该根据实际情况来,在MYSQL数据库中默认的隔离级别是Repeatable read(可重复读)。
4、MySQL中设置事务的隔离级别
# 设置语法:
set [glogal | session] transaction isolation level 隔离级别名称;
set tx_isolation = '隔离级别名称';
# 例子
set session transaction isolation level read committed;
# 查看当前事务的隔离级别
select @@tx_isolation;
记住:设置数据库的隔离级别一定要是在开启事务之前:
隔离级别的设置只对当前连接有效,对于使用MYSQL命令窗口而言,一个窗口就相当于一个连接,当前窗口设置的隔离级别只对当前窗口中的事务有效。
5、事务控制语句
# 开启事务
BEGIN 或 START TRANSACTION 显式地开启一个事务;
# 提交事务
COMMIT 也可以使用 COMMIT WORK,不过二者是等价的。COMMIT 会提交事务,并使已对数据库进行的所有修改成为永久性的;
# 事务回滚
ROLLBACK 也可以使用 ROLLBACK WORK,不过二者是等价的。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;
# 创建保存点
SAVEPOINT identifier,SAVEPOINT 允许在事务中创建一个保存点,一个事务中可以有多个 SAVEPOINT;
# 删除保存点
RELEASE SAVEPOINT identifier 删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常;
# 将事务回滚到保存点
ROLLBACK TO identifier 把事务回滚到标记点;
# 设置事务的隔离级别
SET TRANSACTION 用来设置事务的隔离级别。InnoDB 存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 和 SERIALIZABLE。
6、MySQL事务处理的两种主要方式
(1)、用 BEGIN, ROLLBACK, COMMIT来实现
BEGIN; # 开始一个事务
ROLLBACK; # 事务回滚
COMMIT; # 事务确认
(2)、直接用 SET 来改变 MySQL 的自动提交模式
SET AUTOCOMMIT=0 # 禁止自动提交
SET AUTOCOMMIT=1 # 开启自动提交