大家好!我是黄啊码,前几天有位入门【编程,不是我家门,别想多】不久的小姐姐跟我说:啊码,我做了一个订单系统,但订单没付款前就往数据库插入新数据,结果我这么一直操作就会产生好多 订单,这该咋办?我说:用数据库的事务不就行了?然而她说了一句:啥是事务? 那今天我们就讲讲事务的相关内容:
事务的特性是什么?
事务的特性:要么完全执行,要么都不执行。不过要对事务进行更深一步的理解,还要从事务的 4 个特性说起,这 4 个特性用英文字母来表达就是 ACID。
- A,也就是原子性(Atomicity)。原子的概念就是不可分割,你可以把它理解为组成物质的基本单位,也是我们进行数据处理操作的基本单位。
- C,就是一致性(Consistency)。一致性指的就是数据库在进行事务操作后,会由原来的一致状态,变成另一种一致的状态。也就是说当事务提交后,或者当事务发生回滚后,数据库的完整性约束不能被破坏。
- I,就是隔离性(Isolation)。它指的是每个事务都是彼此独立的,不会受到其他事务的执行影响。也就是说一个事务在提交之前,对其他事务都是不可见的。
- 最后一个 D,指的是持久性(Durability)。事务提交之后对数据的修改是持久性的,即使在系统出故障的情况下,比如系统崩溃或者存储介质发生故障,数据的修改依然是有效的。因为当事务完成,数据库的日志就会被更新,这时可以通过日志,让系统恢复到最后一次成功的更新状态。
事务的控制
当我们了解了事务的特性后,再来看下如何使用事务。我们知道 Oracle 是支持事务的,而在 MySQL 中,则需要选择适合的存储引擎才可以支持事务。如果你使用的是 MySQL,可以通过 SHOW ENGINES 命令来查看当前 MySQL 支持的存储引擎都有哪些,以及这些存储引擎是否支持事务。
可以看出在 MySQL 中,InnoDB 是支持事务的,而 MyISAM 存储引擎不支持事务。
在 MySQL 5.5 版本之前,默认的存储引擎是 MyISAM,在 5.5 版本之后默认存储引擎是 InnoDB。InnoDB 和 MyISAM 区别之一就是 InnoDB 支持事务,也可以说这是 InnoDB 取代 MyISAM 的重要原因。
常用控制语句
- START TRANSACTION 或者 BEGIN,作用是显式开启一个事务。
- COMMIT:提交事务。当提交事务后,对数据库的修改是永久性的。
- ROLLBACK 或者 ROLLBACK TO [SAVEPOINT],意为回滚事务。意思是撤销正在进行的所有没有提交的修改,或者将事务回滚到某个保存点。
- SAVEPOINT:在事务中创建保存点,方便后续针对保存点进行回滚。一个事务中可以存在多个保存点。
- RELEASE SAVEPOINT:删除某个保存点。
- SET TRANSACTION,设置事务的隔离级别。
注:使用事务有两种方式,分别为隐式事务和显式事务。隐式事务实际上就是自动提交,Oracle 默认不自动提交,需要手写 COMMIT 命令,而 MySQL 默认自动提交,当然我们可以配置 MySQL 的参数:
mysql> set autocommit =0; // 关闭自动提交
例子:
CREATE TABLE test(name varchar(255), PRIMARY KEY (name)) ENGINE=InnoDB;
BEGIN;
INSERT INTO test SELECT 'XXX1';
COMMIT;
INSERT INTO test SELECT 'XXX2';
INSERT INTO test SELECT 'XXX3';
ROLLBACK;
SELECT * FROM test;
结果:XXX1
那么我们再来举例:
CREATE TABLE test(name varchar(255), PRIMARY KEY (name)) ENGINE=InnoDB;
SET @@completion_type = 1;
BEGIN;
INSERT INTO test SELECT 'XXX1';
COMMIT;
INSERT INTO test SELECT 'XXX2';
INSERT INTO test SELECT 'XXX2';
ROLLBACK;
SELECT * FROM test;
结果你们肯定会想:输出XXX1和XXX2不对吗?
XXX2是主键,到了第三个insert就会报错,所以一般人认为是插入2条数据,但是这里有:completion_type = 1,这就涉及到关于它的知识点了:
completion_type 参数
- completion=0,这是默认情况。也就是说当我们执行 COMMIT 的时候会提交事务,在执行下一个事务时,还需要我们使用 START TRANSACTION 或者 BEGIN 来开启。
- completion=1,这种情况下,当我们提交事务后,相当于执行了 COMMIT AND CHAIN,也就是开启一个链式事务,即当我们提交事务之后会开启一个相同隔离级别的事务
- completion=2,这种情况下 COMMIT=COMMIT AND RELEASE,也就是当我们提交后,会自动与服务器断开连接。
在上面这段代码里,我使用了 completion_type =1,也就是说当我提交之后,相当于在下一行写了一个 START TRANSACTION 或 BEGIN。这时两次插入“XXX2”会被认为是在同一个事务之内的操作,那么第二次插入“XXX2”就会导致事务失败,而回滚也将这次事务进行了撤销,所以你能看到的结果就只有一个“XXX1”。
总接
事务是数据库区别于文件系统的重要特性之一,当我们有了事务就会让数据库始终保持一致性,同时我们还能通过事务的机制恢复到某个时间点,这样可以保证已提交到数据库的修改不会因为系统崩溃而丢失。最后附上脑图一份,需要自取:
好了,今天的课程就到这里,大家要好好消化一下,多举一反三,有问题的留个言,别忘了一键三连,下次我们还会再见!
我是黄啊码,码字的码,退。。。退。。。退。。。朝!
版权归原作者 黄啊码 所有, 如有侵权,请联系我们删除。