数据库设计和事务

第一节:设计数据库三大范式

范式:Normal Format,符合某一种级别的关系模式的集合,表示一个关系内部各属性之间的联系的合理化程度。 一个数据库表之间的所有字段之间的联系的合理性。

学生表,班级表

  • 范式是离散数学里的概念
  • 范式目标是在满足组织和存储的前提下使数据结构冗余最小化
  • 范式级别越高,表的级别就越标准
  • 目前数据库应用到的范式有以下几层

                        第一范式:1NF

                        第二范式:2NF

                        第三范式:3NF

一个数据库表设计的是否合理,要从增删改查的角度去考虑,操作是否方便

第一范式:确保表中每一列数据的原子性,不可再分!

第二范式:在满足第一范式的基础上,确保列数据要跟主键关联,不能出现部分依赖。

第三范式设计表:再满足第二范式的基础上,保证每一列数据都要跟主键直接关联,不能出现传递依赖。

当数据库到达第三范式的时候,基本上有关数据冗余,数据插入、删除、更新的异常问题得到了解决,这也是一 个”合法的”数据库最基本的要求,但是*效率问题*就另当别论了,因为表越多,连接操作就越多,但是连接是一个 比较耗资源的操作。

在设计数据库的时候,要在满足自己需求的前提下,尽可能的满足三大范式。

第二节:表间的关系

需求分析:

  • 一对一关系: 一个学号对一个姓名

在设计数据库时如果是一对一关系,直接设计成一张表。(如果在字段非常多的情况下,可以做合理的分 表)

  • 一对多关系:(多对一)一个老师多个班级 ,一个班级对多个学生, 订单---》商品 一对多。

设计时主要是通过外键关联。

  • 多对多关系: 学生对课程

设计数据库时,多对多关系,需要一个中间表进行关联!

一对一:学号---》学生姓名

一对多:一个班级--》多个学生

多对多:老师《--》对学生,一个学生可以多个老师,一个老师有多个学生。

班级---》年级 多对一;

学生-- 》班级 多对一;

学生---》课程 多对多;

第二节: 事务管理

1.为什么需要事务 (一件完整的事情)

转账案例:张三给李四转账。

2.使用事务解决问题

事务处理1: 执行过程中遇到错误,回滚事务

 

事务处理2: 执行过程正常,提交事务

 

 3.数据库事务的原理

如果不写start transaction;commit;此时事务自动开启,自动提交;

在数据库中 ,事务都是自动提交的。事务的自动提交就是 执行语句完成之后 就立刻持久化到数库中。

start transaction;开始事务

rollback;回滚事务

commit;提交事务

当我们添加了start transaction;和commit;后 事务的提交就从自动变成手动。因为中途出错,所以导致commit; 不执行,也就是说缓冲区中的数据没有持久化的数据库中。

4.什么是数据库事务

从开启到提交为一个事务。

由此可见,一个事务对应一组业务。一个事务中间可以有一条sql,多条sql。

所以 一个业务开始之前 开启事务 一个业务结束之后 提交事务。

我们这个转账案例:需要几个事务?

可以写成两个事务,但是不合适。因为我们的需求 让张三减的同时让李四加钱。只能写成一个事务。

 5.事务的特征ACID

事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项 的一个程序执行单元(unit)。事务通常由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用户程序的 执行所引起,并用形如start transaction和end transaction语句(或函数调用)来界定。事务由事务开始 (begin transaction)和事务结束(end transaction)之间执行的全体操作组成

再事务开始和结束之间做的所有的事情叫完整事务。

在关系数据库中,一个事务可以是一条SQL语句,一组SQL语句或整个程序。

1、原子性(Atomicity):

事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事 务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子, 是物质构成的基本单位。

2、一致性(Consistency):

事务开始前和结束后,数据库的数据完整性约束没有被破坏,事务前后操作数据是一致的 。比如A向B转账,不可 能A扣了钱,B却没收到。 能量守恒。

3、隔离性(Isolation):

一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行 的各个事务之间不能互相干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。

两个事务之间是有隔离级别,隔离级别的不同会导致出现不同的问题。

此时产生三种读:

脏读 幻读 不可重复读。

4、持久性(Durability):

持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就 应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。

二、事务的并发问题

1、脏读:

事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

场景:公司发工资了,领导把5000元打到Tom的账号上,但是该事务并未提交,而Tom正好去查看账户,发现工 资已经到账,账户多了5000元,非常高兴,可是不幸的是,领导发现发给Tom的工资金额不对,是2000元,于是 迅速回滚了事务,修改金额后,将事务提交,Tom再次查看账户时发现账户只多了2000元,Tom空欢喜一场,从 此郁郁寡欢,走上了不归路…...

2、不可重复读:

事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一 数据时,结果 不一致。

场景:Tom拿着工资卡去消费,酒足饭饱后在收银台买单,服务员告诉他本次消费1000元,Tom将银行卡给服务 员,服务员将银行卡插入POS机,POS机读到卡里余额为3000元,就在Tom磨磨蹭蹭输入密码时,他老婆以迅雷不 及掩耳盗铃之势把Tom工资卡的3000元转到自己账户并提交了事务,当Tom输完密码并点击“确认”按钮后,POS机 检查到Tom的工资卡已经没有钱,扣款失败,Tom十分纳闷,明明卡里有钱,于是怀疑POS有鬼,和收银小姐姐大 打出手,300回合之后终因伤势过重而住进ICU,Tom从此郁郁寡欢,从此走上了不归路......

分析:上述情况即为不可重复读,两个并发的事务,“事务A:POS机扣款”、“事务B:Tom的老婆网上转账”,事务A 事先读取了数据,事务B紧接了更新数据并提交了事务,而事务A再次读取该数据扣款

3、幻读:

已知有两个事务A和B,A从一个表中读取了数据,然后B在该表中插入了一些新数据,导致A再次读取同一个表, 就 会多出几行,简单地说,一个事务中先后读取一个范围的记录,但每次读取的纪录数不同,称之为幻象读

场景:Tom跟朋友聚餐完毕后开启事务付账,先付了80元烟钱,Tom的老婆正好在家里查账发现Tom仅仅有80元 的消费记录,非常吃惊,心想“老公真是太节俭了,嫁给他真好!”,而Tom此时再次支付饭钱1000元,即新增了一 条1000元的消费记录并提交了事务,沉浸在幸福中的老婆不敢相信自己的眼睛,又查询了Tom当天工资卡消费明 细,一探究竟,可查出的结果竟然发现又多了一笔1000元的消费,Tom的老婆瞬间怒气冲天,外卖订购了一个大 号的榴莲,傍晚降临,Tom生活在了水深火热之中,只感到膝盖针扎的痛......

小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的 问题只需锁住满足条件的行,解决幻读需要锁表

对于MySQL的Innodb的默认事务隔离级别是重复读(repeatable read)。可以通过下面的命令查看:

mysql> SELECT @@tx_isolation;--5.7版本
mysql> SELECT @@transaction_isolation; --8.0版本
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ |
+-------------------------+
1 row in set (0.00 sec)
#设置mysql的隔离级别:
#set session transaction isolation level 设置事务隔离级别
#设置read uncommitted级别:
set session transaction isolation level read uncommitted;
#设置read committed级别:
set session transaction isolation level read committed;
#设置repeatable read级别:
set session transaction isolation level repeatable read