事务的使用
1.如何使用事务:
1.1.事务的完成过程:
- 1.步骤1:开启事务
- 2.步骤2:一系列的DML操作
- 3.步骤3:事务结束状态:提交事务(COMMIT),中止事务(事务回滚ROLLBACK)
1.2.事务分类:
- 事务有两种方式:
- 1.
显式事务
- 2.
隐式事务
- 1.
2.显示事务与隐式事务的执行过程
2.1.显示事务的执行过程
a.步骤1:开启事务方式:
- 1.
START TRANSACTION
或者BEGIN
,作用是显式开启一个事务 - 2.
START TRANSACTION
语句相较于BEGIN
特别之处在于,后边可以跟随如下修饰符
- READ ONLY :标识当前事务是一个
只读事务
,也就是属于该事务的数据库操作只能读取数据,而不能修改数据
- READ WRITE :
(默认值)
标识当前事务是一个读写事务
,也就是属于该事务的数据库操作既可以读取数据,也可以修改数据。 WITH CONSISTENT SNAPSHOT
:启动一致性读
- READ ONLY :标识当前事务是一个
- 3.举例说明开启事务:
b.步骤2:一系列DML
操作
c.步骤3:提交事务(COMMIT)或中止事务(事务回滚ROLLBACK)
- 1.
savepoint
:事务操作过程中的一个保存点
,方便事务回滚到某个点的状态
- 2.其中关于
SAVEPOINT的相关操作有
:
2.2.隐式事务执行过程 :
a.关键字:autocommit
- 1.隐式事务中的关键字:
autocommit
- 2.如下可以看出默认是开启隐式事务,所以在此时的
每个DML操作都是自动提交
的。
- 3.默认是ON,如果不显式的使用START TRANSACTION或者BEGIN语句开启一个事务,
那么每一条DML语句都算是一个独立的事务
,这种特性称之为事务的自动提交。也就是说,不以START TRANSACTION或者BEGIN语句显式的开启一个事务,那么下边这两条语句就相当于放到两个独立的事务中去执行
UPDATE account SET balance = balance - 10 WHERE id = 1; #此时这条DML操作是一个独立的事务 UPDATE account SET balance = balance + 10 WHERE id = 2; #此时这条DML操作是一个独立的事务
b.关闭隐式事务中的自动提交:
关闭
自动提交
的功能,可以使用下边两种方法之一:
b1.方式1:
- 1.把
系统变量 autocommit 的值设置为 OFF(针对于DML操作是有效的,对DDL操作是无效的)
,就像这样:SET autocommit = OFF
; 或SET autocommit = 0
;此时,下面的两个语句就不再每一条是事务,假设我后面再执行一条commit或者rollback,那么这两条语句就组合在一起,成为一个事务
SET autocommit = OFF; #或 SET autocommit = 0;
- 2.这样的话,写入的多条语句就算是属于同一个事务了,直到我们显式的写出COMNIT语句来把这个事务提交掉,或者显式的写出ROLLBACK语句来把这个事务回滚掉
b2.方式2:
- 1.显式的的使用
START TRANSACTION
或者BEGIN
语句开启一个事务。这样在本次事务提交或者回滚前会暂时关闭掉自动提交的功能
START TRANSACTION;UPDATE account SET balance = balance - 10 WHERE id = 1;UPDATE account SET balance = balance + 10 WHERE id = 2; COMMIT; #或rollback;
补充:
Oracle 默认不自动提交,需要手写COMMIT命令,而MySQL 默认自动提交
c.关闭隐式事务案例:
- 方式1:使用SET autocommit = FALSE
# 如何关闭自动提交?
SET autocommit = FALSE; #针对于DML操作是有效的,对DDL操作是无效的。
UPDATE account SET balance = balance - 10 WHERE id = 1;
UPDATE account SET balance = balance + 10 WHERE id = 2;
COMMIT; #或rollback;
- 方式2:
在autocommit为true的情况下,使用start transaction 或begin开启事务,那么DML操作就不会自动提交数据
START TRANSACTION;
UPDATE account SET balance = balance - 10 WHERE id = 1;
UPDATE account SET balance = balance + 10 WHERE id = 2;
COMMIT; #或rollback;
3.隐式提交数据的情况都有哪些:
3.1.数据定义语言(Data definition language,缩写为:DDL
)
3.2.隐式使用或修改mysql数据库中的表
3.3.事务控制或关于锁定的语句
- 1.当我们在
一个事务还没提交或者回滚时就又使用 START TRANSACTION 或者 BEGIN 语句开启了另一个事务时,会 隐式的提交 上一个事务
- 2.当前的
autocommit 系统变量的值为 OFF
,我们手动把它调为 ON 时
,也会隐式的提交
前边语句所属的事务`SET autocommit = FALSE; UPDATE account SET balance = balance - 10 WHERE id = 1; UPDATE account SET balance = balance + 10 WHERE id = 2; SET autocommit = true;
- 3.使用
LOCK TABLES 、 UNLOCK TABLES
等关于锁定的语句也会 隐式的提交 前边语句所属的事务。
3.4.加载数据的语句:
- 使用LOAD DATA语句来批量往数据库中导入数据的时候,就会隐式提交前面的所有语句
e.关于mysql的一些复制的一些语句:
3.5.其他一些语句:
5 .事务的使用举例:
5.1.举例1:体会提交与回滚
a.首先明确什么是下DML和DDL的不同:
b.语句操作:
use MyBatis;# 1.使用MyBatis库
CREATE TABLE user3(NAME VARCHAR(15) PRIMARY KEY);# 2.建表
SHOW VARIABLES LIKE 'autocommit';# 3.查看autocommit的,确保是on-------------------------------------------------------------------------------
# 情况一:
BEGIN;# 4.开启事务
INSERT INTO user3 VALUES('张三');# 5.插入语句,且不会自动提交数据,但是select可以查询到
COMMIT;# 6.提交数据,这次事务就完成了BEGIN; #7.再开启一个新的事务
INSERT INTO user3 VALUES('李五'); #8.此时不会自动提交数据
INSERT INTO user3 VALUES('李五'); #9.受主键的影响,不能添加成功
ROLLBACK;# 10.回滚到上次commit的地方,所以:数据库中仅有张三这一条数据-------------------------------------------------------------------------------
# 情况二:
TRUNCATE TABLE user3; #清楚表数据,因为这个是DDL操作会自动提交数据,不会受autocommit变量的影响。BEGIN;#一次事务开始
INSERT INTO user3 VALUES('张三'); #此时不会自动提交数据
COMMIT;#事务完成,提交数据INSERT INTO user3 VALUES('李四');# 7.再次插入数据,语句前面没有写:begin,所以在默认情况下(即autocommit为true),DML操作也会自动提交数据INSERT INTO user3 VALUES('李四');# 8.因为name是主键,所以这里再插入询就报错了,即事务的失败的状态
ROLLBACK # 9.那么我们ROLLBACK,就会回到上次commit的地方,因为第7步有自动提交,所以就会回滚到这个地方。----------------------------------------------------------------------------------------
#情况三
RUNCATE TABLE user3;#1.清楚表数据
SELECT * FROM user3;#2.查看是否清楚成功SELECT @@completion_type;#定义变量,两个@@表示系统变量,默认值是0
SET @@completion_type = 1;# 开启链式BEGIN;#开启一个事务
INSERT INTO user3 VALUES('张三'); # 插入数据
COMMIT;#事务完成INSERT INTO user3 VALUES('李四');# 插入数据,隐式提交
INSERT INTO user3 VALUES('李四'); # 再次插入语句,报错
ROLLBACK;# 回滚到上次提交的地方
SELECT * FROM user3;# 查询表数据,发现现在表中只有张三一条数据,这个就是因为定义了变量的原因,下面来看下这个变量啥意思
c.针对上述案例3,说明下completion_type
的值代表的含义:
- 1.
completion=0
:这是默认情况。当执行COMNIT的时候会提交事务,在执行下一个事务时,还需要使START TRANSACTION 或者BEGIN来开启。 - 2.
completion=1
:这种情况下,当提交事务后,相当于执行了COMMIT AND CHAIN,也就是开启一个链式事务,即提交事务之后会开启一个相同隔离级别的事务。 - 3.
completion=2
:这种情况下CONMMIT=COMMIT AND RELEASE,也就是提交后,会自动与服务器断开连接
5.2.举例2:体会INNODB 和 MyISAM
a.MyISAM
:是不支持事务的
CREATE TABLE test1(i INT) ENGINE = INNODB;
CREATE TABLE test2(i INT) ENGINE = MYISAM;#针对于innodb表
BEGIN
INSERT INTO test1 VALUES (1);
ROLLBACK;
SELECT * FROM test1;#因为回滚了,所以就没有存储数据#针对于myisam表:不支持事务
BEGIN
INSERT INTO test2 VALUES (1);
ROLLBACK;
SELECT * FROM test2;#发现有一条数据,说明ROLLBACK没用,即不支持事务
5.3.举例3:体会savepoint:
CREATE TABLE user3(NAME VARCHAR(15),balance DECIMAL(10,2));# 创建表BEGIN #开启事务
INSERT INTO user3(NAME,balance) VALUES('张三',1000);# 插入一条数据
COMMIT;# 提交数据
SELECT * FROM user3; # 查询数据BEGIN;
UPDATE user3 SET balance = balance - 100 WHERE NAME = '张三';# 更改1
UPDATE user3 SET balance = balance - 100 WHERE NAME = '张三';# 又更改1
SAVEPOINT s1;# 此时设置保存点SELECT * FROM user3;//800元UPDATE user3 SET balance = balance + 1 WHERE NAME = '张三';# 再次update操作
ROLLBACK TO s1; #回滚到设置的保存点那一步,只是回滚,不会自动的提交,待回滚后,再自己输入语句继续进行操作ROLLBACK; # 继续执行回滚操作,又回到了最初的状态。
SELECT * FROM user3;# 查询确认是否回滚成功 1000元