事务和范式是什么
事务
事务概述
概述:在实际的开发过程中,一个业务操作如:转账,往往是要多次访问数据库才能完成的。转账是一
个用户扣钱,另一个用户加钱。如果其中有一条 SQL 语句出现异常,这条 SQL就可能执行失败。事务执
行是一个整体,所有的 SQL 语句都必须执行成功。如果其中有 1 条 SQL 语句出现异常,则所有的 SQL
语句都要回滚,整个业务执行失败。
模拟银行转账:
创建表
CREATE TABLE account (
`id` INT(10) AUTO_INCREMENT PRIMARY KEY ,
`name` VARCHAR(10),
`balance` DOUBLE
);
# 添加数据
INSERT INTO account (name, balance) VALUES ('张三', 1000), ('李四', 1000);
假设,张三给李四转账200元
– 张三账号-200
update account set balance = balance - 200 where name='张三';
– 李四账号+200
update account set balance = balance + 200 where name='李四';
数据正常情况下,完成两条语句不会发生问题,但是,假设当张三账号上-200 元,服务器崩溃
了。李四的账号并没有+200 元,数据就出现问题了。我们需要保证其中一条SQL 语句出现问题,整个转
账就算失败。只有两条 SQL 都成功了转账才算成功。这个时候就需要用到事务。
MYSQL中事务的提交方式
原理:事务开启之后, 所有的操作都会临时保存到事务日志中, 事务日志只有在得到 commit 命令才会同
步到数据表中,其他任何情况都会清空事务日志(rollback,断开连接)
①手动提交
在手动提交方式下,需要显式地调用提交命令来提交事务。在关系型数据库中,通常使用 SQL 语句中的 COMMIT 命令来提交事务。手动提交方式提供了更细粒度的控制,可以在适当的时机进行提交。
SQL语句:
②自动提交
每个单独的数据库操作都被视为一个独立的事务,并在执行完成后自动提交。这意味着每个操作都立即生效,无需显式的提交命令。
手动提交事务
执行过程:开启事务–>执行多条 SQL 语句–>成功提交事务(失败事务的回滚 )
如下图所示:
操作事务步骤
①使用 DOS 控制台进入 MySQL;
②执行以下 SQL 语句:1.开启事务,2.张三账号-200,3.李四账号+200;
③ 使用 Navicat 查看数据库:发现数据并没有改变;
④在控制台执行 commit 提交事务;
⑤使用 Navicat 查看数据库:发现数据改变.
过程截图:
①Win+R进入cmd,输入如下命令(输入自己对应的账号和密码)进入数据库
②开启事务:记住在dos窗口的sql语句记得加分号结束
③选择数据库执行SQL语句,查看初始数据
④执行SQL语句操作,并查询数据库表中数据
⑤通过Navicat工具查看表中数据
上述内容说明,两条语句还没有提交,只是执行完成了。所以数据库中的数据并没有真正的改变。
⑥提交之后查看数据
⑦通过Navicat工具查看表中数据
回滚事务
回滚事务步骤:
①在控制台执行以下 SQL 语句
②使用 Navicat 查看数据库:发现数据并没有改变;
③在控制台执行 rollback 回滚事务;
④使用 Navicat 查看数据库:发现数据未变化.
过程截图:
数据库初始数据
以下分别执行的是,1.开始事务
2.执行张三减少的语句
3.执行李四增加的语句
4.查询数据,此时还没有提交。
用navicat查看数据库数据,因为没有提交所以没有改变
回滚事务并提交
事务总结
如果事务中 SQL 语句没有问题,commit 提交事务,会对数据库的数据进行改变。 如果事务中
SQL 语句有问题,rollback 回滚事务,会回退到开启事务时的状态。
ROLLBACK
语句只能回滚当前事务的更改,无法撤销之前已经提交的事务。一旦事务提交,其中的更改将永久
保存到数据库中,无法通过 ROLLBACK
来撤销。
事务回滚点
在某些成功的操作完成之后,后续的操作有可能成功有可能失败,但是不管成功还是失败,前面操作都
已经成功,可以在当前成功的位置设置一个回滚点。可以供后续失败操作返回到该位置,而不是返回所
有操作,这个点称之为回滚点。
回滚点SQL语句
我们使用navicat来操作
第一步:查看初始化数据
第二步:开启事务,执行sql语句,并设置回滚点
START TRANSACTION
update account set balance = balance - 100 where name='张三';
update account set balance = balance + 100 where name='李四';
SAVEPOINT change_balance;
查看数据(此时未提交)
第三步:再次执行增加删除操作,并查看数据
update account set balance = balance - 100 where name='张三';
update account set balance = balance + 100 where name='李四';
SELECT *from account;
第四步:我们回滚到设置的回滚点,查看数据
ROLLBACK to change_balance;
COMMIT;
SELECT *from accoun
完整代码
START TRANSACTION
update account set balance = balance - 100 where name='张三';
update account set balance = balance + 100 where name='李四';
SAVEPOINT change_balance;
SELECT *from account;
update account set balance = balance - 100 where name='张三';
update account set balance = balance + 100 where name='李四';
SELECT *from account;
ROLLBACK to change_balance;
COMMIT;
SELECT *from account;
事务的四大特征(ACID)
事务并发时出现的问题
因为某一刻不可能总只有一个事务在运行,可能出现A在操作t_account表中的数据,B也同样在操作t_account表,那么就会出现并发问题,对于同时运行的多个事务,当这些事务访问数据库中相同的数据时,如果没有采用必要的隔离机制,就会发生以下各种并发问题。
脏读
A事务读取B事务尚未提交的更改数据,并在这个数据的基础上操作。如果恰巧B事务回滚,那么A事务读到的数据根本是不被承认的。
不可重复读
不可重复读是指 A事务读取了B事务已经提交的更改数据。,例:事务A两次读取数据,第一次余额400元,第二次余额1000元,而两次读取出现不一样的情况是因为在第一次和第二次读取数据之间的空档期,事务更改了数据.导致第二次读取数据出现偏差.
幻读
A事务读取B事务提交的新增数据,这时A事务将出现幻读的问题。例:事务A先读取了表的数据,然后事务B又往表中添加了几行数据,导致A事务再次读取表的时候,会发现表的数据发生了变化.就像发生了幻像一样.
事务隔离级别
为了解决多个事务的并发问题,数据库系统提供了四种事务隔离级别供用户选择。
读未提交
允许事务读取未被其他事务提交的变更。(脏读、不可重复读和幻读的问题都会出现)
读已提交
只允许事务读取已经被其他事务提交的变更。(因为只能读取已经被提交的事务,所以就能避免因为读取没提交的数据而产生的脏读)
可重复读
确保事务可以多次从一个字段中读取相同的值,在这个事务持续期间,禁止其他事务对这个字段进行更新(update)。(可以避免脏读和不可重复读,但幻读仍然存在)
串行化(serializable)
确保事务可以从一个表中读取相同的行,在这个事务持续期间,禁止其他事务对该表执行插入、更新和删除操作,所有并发问题都可避免,但性能十分低下(因为你不完成就都不可以弄,效率太低)
数据库引擎
nnodb:frm是表定义文件,ibd是数据文件
MyISAM:frm是表定义文件,myd是数据文件,myi是索引文件
Mysql默认引擎是Innodb
范式
一、什么是范式
好的数据库设计对数据的存储性能和后期的程序开发,都会产生重要的影响。建立科学的,规范的数据
库就需要满足一些规则来优化数据的设计和存储,这些规则就称为范式。
1、三大范式
目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范
式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。
满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多规范要求的称为第二范
式(2NF), 其余范式以次类推。一般说来,数据库只需满足第三范式(3NF)就行了。
1.1、第一范式(1NF)
概述:数据库表的每一列都是不可分割的原子数据项,不能是集合、数组等非原子数据项。即表中的某
个列有多个值时,必须拆分为不同的列。简而言之,第一范式每一列不可再拆分,称为原子性。
1.2、第二范式(2NF)
概述:在满足第一范式的前提下,表中的每一个字段都完全依赖于主键。 所谓完全依赖是指不能存在仅
依赖主键一部分的列。简而言之,第二范式就是在第一范式的基础上所有列完全依赖于主键列。
当存在一个复合主键包含多个主键列的时候,才会发生不符合第二范式的情况。比如有一个主键有 两个
列,不能存在这样的属性,它只依赖于其中一个列,这就是不符合第二范式。
特点:
①一张表只描述一件事情;
②表中的每一列都完全依赖于主键。
1.3、第三范式(3NF)
概念: 在满足第二范式的前提下,表中的每一列都直接依赖于主键,而不是通过其它的列来间接依赖于
主键。 简而言之,第三范式就是所有列不依赖于其它非主键列,也就是在满足 2NF 的基础上,任何非主
列不得传递 依赖于主键。所谓传递依赖,指的是如果存在"A → B → C"的决定关系,则 C 传递依赖于
A。因此,满足第三范 式的数据库表应该不存在如下依赖关系:主键列 → 非主键列 x → 非主键列 y。
总结: