事务概念
1、什么是事务?
事务(Transaction)是访问并且可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由高级数据库操纵语言或者编程语言书写的用户程序的执行所引起。事务由“事务开始”和“事务结束”之间的全体操作组成,是一系列要发生的连续的操作。
2、事务执行原理
mysql允许将书屋统一进行管理(innodb引擎支持),将用户所做的操作,暂时保存起来,不直接方法数据表中(更新操作),等到用户确认结果之后再进行操作。
事务安全的意义:保证数据操作的完整性。
- 内连接进行多表查询
- 显式内连接: select * from 表1 inner join 表2 on 清除笛卡尔积条件 and 其他的条件
- 隐式内连接: select * from 表1 表2 where 清除笛卡尔积条件 and 其他的条件
- 使用左外连接和右外连接进行多表查询
- 左外连接: select * from 表1 left outer join 表2 on 清除笛卡尔积条件 and 其他的条件
- 右外连接: select * from 表1 right outer join 表2 on 清除笛卡尔积条件 and 其他的条件
- 使用子查询进行多表查询
- 一条sql嵌套了另外一条sql语句
- 多表查询的规律
- 子查询如果是一个值, 出现where 使用比较运算符
- 子查询如果是单列多行: where in
- 子查询的结果是多行多列的: 当成临时表去使用
- 事务的概念
- 事务应用场景:(原子性) 多条sql语句执行的时候要不一起成功,要不就一起失败。
- 事务的原理
- 如果一个事务没有提交之前,提交的sql语句其实本质上就记录日志文件上的,并没有真正的提交到数据库中。
- 在MySQL中使用事务:
- start tranasaction
- rollback
- commit;
- 脏读,不可重复读,幻读的概念及解决办法:
- 脏读: 一个事务读取到另外一个事务没有提交的数据 read commmitted
- 不可重复读: 一个事务读取同一条数据,多次读取到的结果是不一致的 repeatable read
- 幻读: 一个事务读取到了另外一个事务新插入或者是删除的数据,
- 1.在实际的业务开发中,有些业务操作要多次访问数据库。一个业务要发送多条SQL语句给数据库执行。需要将多次访
问数据库的操作视为一个整体来执行,要么所有的SQL语句全部执行成功。如果其中有一条SQL语句失败,就进行事
务的回滚,所有的SQL语句全部执行失败。
- 数据准备:
#创建数据表
CREATE TABLE account(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(10),
balance DOUBLE
);
#添加数据
INSERT INTO account(NAME,balance)VALUES('张三',1000),('李四',1000);
- 比如:张三给李四转500块钱,银行需要做的事情。
- 1.先扣除张三的500块钱:UPDATE account SET balance=balance-500 WHERE NAME='张三';
- 2.先给李四加500块钱:UPDATE account SET balance=balance+500 WHERE NAME='李四';
- 但是如果先扣除了张三的钱,然后突然间断电了,那么李四没有添加成功。其实对于这种需求我们应该要保证多条SQL语句要不一起成功,要不一起失败。
2.2 事务的基本操作
2.2.1 事务相关的命令:
- 开启事务 start transaction
- 回滚事务 rollback
- 提交事务 commit
2.2.2 事务的操作
2.2.2.1 准备数据:
-
#创建数据表
-
CREATE TABLE account(
-
id INT PRIMARY KEY AUTO_INCREMENT,
-
NAME VARCHAR(10),
-
balance DOUBLE
-
);
-
#添加数据
-
INSERT INTO account(NAME,balance)VALUES('张三',1000),('李四',1000);
2.2.2.2案例演示:
需求1:张三给李四转账500,中间没有任何的问题,事物正常的提交。
需求2:张三给李四转账500块钱,先扣除了张三500块钱,然后事物回滚,观察数据是否有变化。
- 虽然李四查询看到的数据是1500,但是张三执行了rollback回滚操作,钱并没有真正进入李四的账户,数据库中显示的数据还是1000。
2.4 手动提交事务与自动提交事务:
- 在mysql中如果没有手动开启事物(start transaction),默认情况下是会自动提交SQL语句的,只有手动开启事物,然后才需要手动提交事物。
2.4.1 查看当前事务提交的方式:
- show variables like '%commit%'; 查询事务提交相关的所有变量
修改事物提交的方式
2.5 事务的原理:
2.6 事务回滚点:
- 当前如果直接使用rollable语句,那么会把所有SQL语句执行全部回滚,但是有时候我只希望回滚一部分。那么这时候我们就需要设置事务的回滚点。事务的回滚点就是一个标记。
需求:扣除张三的30块钱,扣除李四40块钱,回滚事务,让李四的回滚,张三的生效。
2.7 事务的四大特性:(面试)ACID
事务特性 | 含义 |
原子性(Atomicity) | 事务是一个不可分割的工作单元,事务中的操作要么都发生,要么都不发生 |
一致性(consistency) | 事务前后数据的完整性必须保持一致(转账前后账户的总额是不变的) |
隔离性(Isolation) | 是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离,不能相互影响。 |
持久性(Durability) | 指一个事务一旦提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发送故障也不应该对其有任何影响。 |
2.8 事务的隔离级别:
- 如果某个数据被多个事务并发执行的时候其实会产生一些不好的现象。
- 不好的现象:
- 脏读。
- 不可重读。
- 幻读(虚读)。
- 我们需要解决这些不好的现象,需要设置事务的隔离级别去解决,数据库中的隔离级别:
- read uncommitted;读取没有提交的数据 --脏读
- read committed;读取提交的数据 --解决脏读,但是不能解决不可重复读。
- repeatable read;可重复读(默认) --解决不可重复读,但是不能解决幻读(幻读在mysql中不存在。默认就已经解决了)
- Serializable --串行化 -------------------解决全部问题,但不推荐使用。
2.8.1查看与设置隔离级别:
- 查看隔离级别:select @@tx_isolation;
- 隔离级别:set global transaction isolation level
- 设置事务的隔离级别如果需要生效,那么需要退出登录,然后重新连接才可以生效。
2.9 脏读:
- 一个事务读取到了另一个事务没有提交的数据。
- 场景:张三在淘宝向李四下单,张三开启事务给李四转账500块钱,然后没有提交事务,通知李四查看账户的总额,李四读取到了张三没有提交的事务数据,然后发货了。张三回滚事务。
- 步骤:
- 张三开启事务,给李四转账500块钱。
- 通知李四查看账户的总额。
- 张三回滚事务。
张三的动作:
李四的动作:
- 脏读的解决方案:把事务的隔离级别提高至:read committed;
2.10 不可重复读:
- 在同一个事务中多次读取同一条数据,读取到的结果是不一致的。
- 可重复读:在一个事务中多次读取同一条数据,读取到结果是一致的。
- 需求:张三10:00的时候在ATM机查看自己的总额,屏幕上显示出是1000大元,然后张三在10:05分打印凭条(10:00)1500,李四在10:03分给张三转账500块钱。
张三的行为:
李四的行为:
- 不可重读的解决方案:把事务的隔离级别提高至repeatable read;
2.11 幻读(虚读):
- 幻读概念:一个事务读取到另一个事务新插入、删除的数据。(数据的总量不变)
- 需求:张三先给老板展示当前的注册人数,然后再打印报表,但是在打印报表之前又来了另外一个人注册,那么报表的数据显示给老板看的数据不一致。
张三的动作:
李四的动作:
3.手动事务
手动事务:整个事务从开始到结束都需要用户(程序员)手动发送指令来实现。
手动事务执行步骤
步骤一:开启事务
start transaction; //开启事务,从这条语句开始,后面的所有语句都不会直接写入到数据表中中,而是保存在事务日志中
步骤二:执行事务,多条写指令构成。
步骤三:设置回滚点(非必须)
当有一系列事务操作时,二其中的步骤如果成功了,没有必要重新来过,可以在某个执行成功的点,设置一个记号(回滚点),然后如果有失败,就可以回到这个记号位置。
注意:在一个事务中可以有多个回滚点,但是如果回到了前面的回滚点,后面的回滚点就失效了。
建立回滚点:
savepoint 回滚点名称; //通常有字母数字和下划线构成
回到回滚点:
rollback 回滚点名称; //该回滚点之后的所有操作清除
步骤四:提交事务/回滚
commit/rollback; // 提交/回滚
事务特性
事务因具有4个属性:原子性(atomicity)、一致性(consistency)、隔离性(isolation)、持久性/永久性(durability / permanence)。
原子性:一个事务是一个不可分割的工作单位,事务中包括的诸多操作要么都做,要么都不做。
一致性:事务必须是使数据库从一个一致性状态转变到另一个一致性状态。与原子性紧密相关。
隔离性:一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
隔离级别(行隔离、表隔离。。。):如果条件中使用了索引(通常是主键),那么系统是根据主键直接找到某条记录,这时与其他记录无关,只隔离一条记录;反之,如果是通过未使用索引(如全表检索),被检索的所有数据都会被锁定(整表)。
持久性:一个事务一旦提交,它对数据库中数据的改变是永久的(不能再使用rollback回滚)。即一个事务使用commit;/rollback;之后该事务便会结束消失。除非通过另一个事务操作数据,否则该数据便是永不改变的。