1. 概 述
-
事务:为了达成某一件事,我们可能需要做出一系列的操作。假如把这一系列的操作看成一个不可分割的整体,那么这个整体,我们便可称之为事务。
-
数据库中的事务:它由一组相关的dml语句组成,该组dml语句,要么全部执行成功,要么全部执行失败,不允许执行一半。用于保证数据的一致性。典型例子如银行转账。
-
事务和锁:当执行事务操作时,mysql会在表上加锁,防止其它用户改表的数据。
2. 事务的操作
mysql数据库控制事务的几个操作:
(1)start transaction – 开始事务
(2)savepoint 保存点名 – 设置保存点
(3)rollback to 保存点名 – 回退事务
(4)rollback – 回退全部事务
(5)commit – 提交事务,所有的操作生效,不能回退
下面以具体的例子,执行一下上面的几个操作。
-- 1. 新建一个表department
CREATE TABLE `department`(
`id` INT PRIMARY KEY, -- 部门号
`name` VARCHAR(30), -- 部门名称
`number` INT -- 部门人数
);
-- 2. 开始事务
START TRANSACTION;
-- 3. 设置保存点
SAVEPOINT a;
-- 4. 执行dml操作
INSERT INTO `department`(`id`,`name`,`number`)
VALUES ('2004522','部门21','300');
-- 5. 设置保存点b
SAVEPOINT b;
-- 6. 再执行dml操作
INSERT INTO `department`(`id`,`name`,`number`)
VALUES ('2065422','部门22','400');
-- 7. 回退到b保存点
ROLLBACK TO b;
-- 8. 回退到a保存点
ROLLBACK TO a;
-- 9. 提交事务,确认修改,结束本次事务
COMMIT;
创建表–开始事务–设置保存点a–执行dml操作–设置保存点b–执行dml操作结果
执行回退到b保存点操作结果
执行回退到a保存点操作结果
注意要点:
- 如果不开始事务,默认情况下,dml操作是自动提交,不能回滚
- 开始一个事务,没有创建保存点,当执行rollback,默认回退到事务开始的状态
- 在一个尚未执行提交的事务中,可以创建多个保存点
- 在一个尚未执行提交的事务中,可以自主选择回退到任一保存点
- mysql的事务机制需要使用innodb存储引擎支持,myisam不支持事务
- 关闭事务的自动提交,同时开始一个事务 set autocommit = off;
3. 事务的特性
事务有4个特性,简称为acid特性,分别是:
- 原子性(Atomicity)
- 一致性(Consistency)
- 隔离性(isolation)
- 持久性(durability)
(1)原子性:是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
(2)一致性:事务必须使数据库从一个一致性状态转变到另外一个一致性状态。
(3)隔离性:指多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其它事务的操作数据所干扰,多个并发事务之间要相互隔离。
(4)持久性:指一个事务一旦被提交,它对数据库中的数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
4. 事务的隔离级别
4.1 事务的隔离问题
(1)多个连接开启各自的事务,操作数据库中的数据时,数据库系统负责隔离操作,以保证各个连接在获取数据时的准确性。
(2)如果不考虑事务的隔离性,可能存在的问题:
- 脏读
- 不可重复读
- 幻读
脏读:当一个事务能读取另一个事务尚未提交的修改(update)时,产生脏读。
不可重复读:同一个查询语句在同一个事务中多次执行,由于其它事务提交了它们所做的修改(update)或者删除(delete)操作,导致该查询语句每次得到的查询结果都不相同,此时发生不可重复读。
幻读:同一个查询语句在同一个事务中多次执行,由于其它事务提交了它们所做的插入(insert)操作,导致该查询语句每次得到的查询结果都不相同,此时发生幻读。
4.2 事务的隔离级别
(1)mysql的事务隔离级别定义了事务与事务之间的隔离程度。
(2)mysql的事务隔离级别分为4种,分别是:
- 读未提交(read uncommitted)
- 读已提交(read committed)
- 可重复读(repeatable read)
- 可串行化(serializable)
隔离级别 | 脏读 | 不可重复读 | 幻读 | 加锁读 |
---|---|---|---|---|
读未提交 | √ | √ | √ | 不加锁 |
读已提交 | × | √ | √ | 不加锁 |
可重复读 | × | × | × | 不加锁 |
可串行化 | × | × | × | 加锁 |
4.2 与隔离级别相关的语句
- 查看当前会话的隔离级别:
SELECT @@transaction_isolation;
- 查看系统当前的隔离级别:
SELECT @@global.transaction_isolation;
- 更改当前会话的隔离级别:
-- 格式
SET SESSION TRANSACTION ISOLATION LEVEL 隔离级别名称;
-- 示例
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
- 更改系统当前的隔离级别:
-- 格式
SET GLOBAL TRANSACTION ISOLATION LEVEL 隔离级别名称;
-- 示例
SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
- 全局修改默认的隔离级别:
-- 找到安装目录中的my.ini配置文件,在里面加上
transaction-isolation = 隔离级别名称
注意要点:
- 隔离级别必须与事务有关,离开事务谈隔离级别没有意义
- 更改隔离级别,不需要先开启事务
- mysql默认的事务隔离级别时可重复读(repeatable read)