第九章:第22节 MySQL基础篇——事务控制语言(DTL)

更新于:2020-12-19 22:17:28

开启事务在MySQL中是非常重要的,它能起到保证数据的安全。



InnoDB存储引擎支持事务,Myisam不支持,这就是InnoDB比Myisam用的多的主要原因。


什么是事务

通常,在此之前,我们说,一条语句使用一个分号(;)来结束,并得到执行。

那么我们说,这个“一次性执行”的过程,可以称为“一个事务”。

简单来说,“一条sql语句,就是一个事务”。

则:

数据库(自然包括mysql数据库)中的事务,是指,可以将“多条语句”的执行,当作“一条语句”来看到的一种内部机制。

即:“事务”是一种可以保证“多条语句一次性执行完成”或“一条都不执行”的机制,即多条SQL语句要么全部执行成功,要么一个都不执行。

为什么需要事务?

看一个实际应用需求(银行存款):表名cunkuan

1.png

银行转账:现在,test1突然需要一笔钱,买iPhone6,向test2借钱4000。

第一步: update  cunkuan  set 存款=存款-4000  where id=2;

第一步做完,突然断电了或者程序因为其他原因报错了,下面第二步执行不了了。

第二步: update  cunkuan  set 存款=存款+4000  where id=1;

则如果没有事务,就可能发生这种事情(惨案)。

如果有了事务,则就可以避免该事情(第二步不执行,第一步执行的结果不生效)。

事务可以看作是一个“容器”,将多条语句,放入该容器,最后,只要一个命令行,来决定其中的所有语句是否“执行”。


往深了讲:


执行一条SQL语句,先在内存里运算完得到最终的数据结果,然后把数据结果写入硬盘。


开启事务后,

执行一条SQL语句,先在内存里运算完得到最终的数据结果,暂时不把数据结果写入硬盘。

接着执行下一条,直到整个事务的所有SQL语句执行完毕,一块把数据结果写入硬盘。


如果中间出现了差错,“回滚事务”,整个事务的已经执行的SQL语句作废。


事务的特点

原子性:一个事务中的所有语句,应该做到:要么全做,要么一个都不做。


一致性:让数据保持逻辑上的“合理性”,比如:一个商品出库时,既要让商品库中的该商品数量减1,又要让对应用户的购物车中的该商品加1。


隔离性:如果多个事务同时并发执行,但每个事务就像各自独立执行一样。


持久性:一个事务执行成功,则对数据来说应该是一个明确的硬盘数据更改(而不仅仅是内存中的变化)。

事务模式:

事务模式:就是让每条执行语句是否当作“一个事务”来看到的设定项。

 

mysql默认安装好之后,其事务模式是:一条语句当作一个事务。


比如:

拿user_info做例子,它是InnoDB存储引擎的表


1.png


数据主键ID最高是25

1.png

在cmd中插入新数据:

1.png


在Navicat中打开:

1.png


说明:cmd和Navicat是MySQL两个不同的终端,像这样的情况基本上说明数据已存入到MySQL(硬盘)里了。


我们可以将其修改为:事务需要“认可”模式:

set  autocommit = 0;  

//false,关闭该模式,即此时不再是一条语句一个事务了。

//结果是:必须使用commit语句才能够生效。


看下面的SQL语句:

1.png

关闭自动事务提交,插入新数据,在cmd终端下显示插入成功了,用select查询语句也能查到。


在Navicat下刷新下:

不显示新插入的数据。(不信的话大家自己去做测试)


在cmd下执行:

1.png


再刷新Navicat,有了:

1.png


 

注意:

autocommit = 0 时,每条语句的默认行为都不会自动提交,需要commit;来提交。

autocommit = 1 时,我们也仍然可以使用事务的完整流程模式来实现事务,如下:


事务的基本实现流程:

1,声明事务开始:start transaction; 或者 begin;

2, 设定多条要执行的具体语句,比如:insertupdatedelete, select。。。其实就是执行,只是这些执行的语句,并不“生效”——其只是内存状态下的执行,而不是物理状态的执行。

3,判断是否需要执行该些语句,在PHP下的逻辑通常这样:

if( 判断是否有错误){

//执行——才针对执行了物理性改变——即生效。

commit;

}

eslse{

//回滚——不执行任何语句。

rollback;

}


发生错误,cmd中直接观察,php中通过语句的返回结果是否为false判断。

 

使用事务完整转账这件事情(假设为cmd模式):

start  transaction;

#第一步:

update  cunkuan  set 存款=存款-4000  where id=2

#第一步做完,突然断电了?

#第二步:

update  cunkuan  set 存款=存款+4000  where id=1

则如果这两条语句都没有错误,就可以:

commit;

但,如果其中发生了错误,则可以:

rollback

1.png


额外说明:


1)默认rollback

开启一个事务后,执行了多条SQL语句,既没有commit也没有rollback,就把终端关闭了(适用于所有终端),那MySQL默认rollback,不会提交的。


2)默认commit

在一个事务的结尾直接“begin”开启新的事务,会默认“commit”提交前一个事务的。


有些语句不能被回滚直接提交。通常,这些语句包括数据定义语言(DDL)语句,比如创建或取消数据库的语句,和创建、取消或更改表或存储的子程序的语句

在设计事务时,不应包含这类语句。如果在事务的过程中发布了一个不能被回滚的语句,则后面的其它语句即便发生错误,在这些情况下,通过发布ROLLBACK语句不能回滚事务的全部效果。


楠神在PHP项目、cmd中都测试过,开启事务后执行了多条SQL语句,因为程序的出错,脚本结束了,也意味着PHP脚本终端关闭了,前面执行的SQL语句都没有执行。


总结:


这节我们先简单了解下事务是什么,怎么用。关于事务的知识远没有结束,MySQL锁的机制就和事务紧密相关,下一章会重点介绍。


什么是锁?


就像上面的转账功能,两个账户一个减一个增,两条update语句,事务能保证两条update语句一块执行。而锁的作用可保证在执行这两条update语句的时候,不让额外的其他SQL语句影响了这两条update语句的执行,确保数据安全。所以在执行这两条update语句时需要给相应的数据加上锁,申明我正在操作,其他的语句先靠边。


楠神觉着MySQL是PHP项目的核心内容,而表结构设计、索引、事务是MySQL的核心内容(表结构设计合理,易读,减少数据量,提高效率;索引添加的好可提高查询效率;事务可保证数据修改的安全性)。我们所学的SQL语句只是让我们学会了怎么用MySQL,而表结构设计、索引、事务的一些相关知识、原理只有了解了,学好了,才能用好MySQL


本节学习代码》》》