TCL:事务控制语言
TCL(Transaction Control Language)
一、事务
1. 事务的概念
一个或一组sql语句组成一个执行单元,这个执行单元要么全部执行,要么全部不执行
2. 事务的特性(ACID)
- 原子性(Atomicity):一个事务不可再分割,要么都执行要么都不执行
- 一致性(Consistency):一个事务执行会使数据从一个一致状态切换到另外一个一致状态
- 隔离性(Isolation):一个事务的执行不受其他事务的干扰
- 持久性(Durability):一个事务一旦提交,则会永久的改变数据库的数据.
3. 事务的使用步骤
-
隐式(自动)事务:没有明显的开启和结束,本身就是一条事务可以自动提交,比如insert、update、delete。autocommit为ON时则表示处于自动事务状态
#在MySQL中查看autocommit状态 SHOW VARIABLES LIKE 'autocommit';
-
显式事务:事务具有明显的开启和结束的标记;前提:必须先设置自动提交功能为禁用(将autocommit设置为OFF)
3.1 事务的提交
事务语句一般只是基本的增删改查:select insert update delete,对于库表的操作,例如 alter drop等,不将其作为事务语句
#步骤1:开启事务
set autocommit=0;#设置自动提交功能为禁用
start transaction;#可选的
#步骤2:编写事务中的sql语句(select insert update delete)
语句1;
语句2;
...
#步骤3:结束事务,一般为提交事务或者回滚事务
commit;提交事务
#开启事务
SET autocommit=0;
START TRANSACTION;
#编写一组事务的语句
INSERT INTO major VALUES(1,'java');
INSERT INTO major VALUES(2,'c++');
#结束事务
commit;
值得注意的是更新和提交是两个概念。上面的sql语句中,执行commit语句之前,两条数据只是暂时放在内存中,只有当执行完commit语句后,磁盘中的数据库才发生更改。
那么如果结束事务的语句不是commit,而是rollback回滚,则这两条数据并不会存到磁盘中,即数据库不会发生改变
3.2 事务的回滚
3.2.1 基本操作
在结束事务时将commit改为rollback即可
#开启事务
SET autocommit=0;
START TRANSACTION;
#编写一组事务的语句
INSERT INTO major VALUES(1,'java');
INSERT INTO major VALUES(2,'c++');
#结束事务
commit;
#rollback;
3.2.2 保存点
保存点(回滚点)savepoint:保存事务状态的节点
#设置保存点
SAVEPOINT 保存点名;
#回滚到指定保存点
ROLLBACK TO 保存点名;
下面的事务结束后,id为2的不会删除,1会删除
SET autocommit=0;
DELETE FROM major WHERE id = 1;
SAVEPOINT a;#设置保存点a
DELETE FROM major WHERE id = 2;
ROLLBACK TO a;#回滚到保存点a
3.2.3 delete和truncate在回滚时候的区别
delete删除可以回滚,truncate删除不可以回滚
#delete删除
SET autocommit=0;
START TRANSACTION;
DELETE FROM major;#执行完不会删
ROLLBACK;
#truncate删除
SET autocommit=0;
START TRANSACTION;
TRUNCATE TABLE major;#执行完会删
ROLLBACK;
SELECT * FROM major;
二、并发事务
1. 并发事务的概念
多个事务同时操作同一个数据库的相同数据时,称为并发事务,如果没有采取必要的隔离机制,容易出现事务的并发问题
2. 常见的并发问题
- 脏读:一个事务读取了其他事务更新但没有提交的数据
- 幻读:一个事务读取了其他事务插入或删除但没有提交的数据
- 不可重复读:一个事务多次读取,结果不一样
3. 事务的隔离性与隔离级别
数据库事务的隔离性: 数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响。 因此需要设置隔离级别来解决并发问题
隔离级别:一个事务与其他事务隔离的程度称为隔离级别。 数据库规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性越弱。下表为隔离级别与能否解决并发问题的对应关系
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
read uncommitted:读未提交(允许事务读取未被其它事务提交的变更) | × | × | × |
read committed:读已提交(只允许事务读取已经被其它事务提交的变更,只能 避免脏读) | √ | × | × |
repeatable read:可重复读(确保事务多次从一个字段中读取相同的值,在这个事务持续期间,禁止其他事务对这个字段进行更新,可以避免脏读和不可重复读) | √ | √ | × |
serializable:串行化(确保事务可以从一个表中读取相同的行,在这个事务持续期间,禁止其他事务对该表执行插入、更新和删除操作,所有并发问题都可以避免,但性能低下) | √ | √ | √ |
(Oracle 支持的2 种事务隔离级别:read committed(默认), serializable;MySQL支持4种隔离级别,默认为repeatable read)
每启动一个MySQL程序,就会获得一个单独的数据库连接,每个连接都有一个全局变量@@transaction_isolation
,表示当前的事务隔离级别
#查看当前MySQL连接的隔离级别
select @@transaction_isolation; # 旧版本可以用别名tx_isolation,新版本不可以
#设置当前MySQL连接的隔离级别
#set session transaction isolation level 隔离级别;
set session transaction isolation level read uncommitted;
#设置整个数据库系统全局的隔离级别,设置完需要重启
set global transaction isolation level 隔离级别;