一、数据库设计三大范式简介
1、第一范式(确保每列保持原子性)
2、第二范式(确保表中的每列都和主键相关)
3、第三范式(确保每列都和主键直接相关,而不是间接相关)
二、事务的概念
- 事务是一种机制、一个操作序列,包含了一组数据库操作命令,并且把所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令要么都执行,要么都不执行
- 是一个不可分割的工作逻辑单元,在数据库系统上执行并发操作时,事务是最小的控制单元
- 适用于多用户同时操作的数据库系统的场景,如银行、保险公司及证券交易系统等等
- 通过事务的整体性以保证数据的一致性
三、事务的ACID特点
- 原子性(Atomicity)
- 事务是一个完整的操作,事务的各元素是不可分的
- 事务中的所有元素必须作为一个整体提交或回滚
- 如果事务中的任何元素失败,则整个事务将失败
- 一致性(Consistency)
- 当事务完成时,数据必须处于一致状态
- 子啊事务开始前,数据库中存储的数据处于一致状态
- 在正在进行的事务中,数据可能处于不一致的状态
- 当事务成功完成时,数据必须再次回到已知的已知状态
- 隔离性(Isolation)
- 对数据进行修改的所有并发事务是彼此隔离额,表明事务必须是独立的,它不应以任何方式依赖于影响其他事务
- 修改数据的事务可在另一个使用相同数据的事务开始之前访问这些数据,或者在另一个使用相同数据的事务结束之后访问这些数据
- 持久性(Durability)
- 指不管系统是否发生故障,事务处理的结果都是永久的
- 一旦事务被提交,事务的效果会被永久地保存在数据库中
四、事务控制语句
-
MySQL事务默认是自动提交的,当SQL语句提交时事务便自动提交
-
事务控制语句
- BEGIN或START TRANSACTION
- COMMIT
- ROLLBACK
- SAVEPOINT identifier
- RELEASE SAVEPOINT identifier
- ROLLBACK TO identifier
- SET TRANSACTION
- 使用处理命令控制事务
- begin:开启一个事务
- commit:提交一个事务
- rollback:回滚一个事务
- 使用set命令进行控制
- set autocommit=0:禁止自动提交
- set autocommit=1:开启自动提交
五、事务的操作实例
例1:在数据库中有一张表test,在写入记录后执行回滚操作
mysql> begin; ## 开始事务
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test value('1','zhangsan'); ## 插入一条记录
Query OK, 1 row affected (0.00 sec)
mysql> select * from test; ## 查看记录
+----+----------+
| id | name |
+----+----------+
| 1 | zhangsan |
+----+----------+
1 row in set (0.00 sec)
mysql> rollback; ## 执行回滚操作
Query OK, 0 rows affected (0.00 sec)
mysql> select * from test; ## 再次查看记录发现已经没有了
Empty set (0.00 sec)
例2:首先使用命令关闭自动提交功能,执行插入命令后再开启自动提交功能,再执行回滚,查看记录是否会保存
mysql> set autocommit=0; ## 关闭事务自动提交
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test value('1','zhangsan'); ## 插入一条记录
Query OK, 1 row affected (0.01 sec)
mysql> set autocommit=1; ## 开启事务自动提交
Query OK, 0 rows affected (0.00 sec)
mysql> rollback; ## 执行回滚操作
Query OK, 0 rows affected (0.00 sec)
mysql> select * from test; ## 查看表内所有记录
+----+----------+
| id | name |
+----+----------+
| 1 | zhangsan |
+----+----------+
1 row in set (0.00 sec)
例3:理解保存点(savepoint)
mysql> begin; ## 开始事务
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test value('1','zhangsan'); ## 插入一条记录
Query OK, 1 row affected (0.00 sec)
mysql> savepoint a; ## 创建保存点a
Query OK, 0 rows affected (0.00 sec)
mysql> select * from test; ## 查看表中记录
+----+----------+
| id | name |
+----+----------+
| 1 | zhangsan |
+----+----------+
1 row in set (0.00 sec)
mysql> insert into test value('2','lisi'); ## 插入一条记录
Query OK, 1 row affected (0.00 sec)
mysql> savepoint b; ## 创建保存点b
Query OK, 0 rows affected (0.00 sec)
mysql> select * from test; ##查看表中记录
+----+----------+
| id | name |
+----+----------+
| 1 | zhangsan |
| 2 | lisi |
+----+----------+
2 rows in set (0.00 sec)
mysql> rollback to a; ## 回滚到保存点a
Query OK, 0 rows affected (0.00 sec)
mysql> select * from test; ## 查看表中记录
+----+----------+
| id | name |
+----+----------+
| 1 | zhangsan |
+----+----------+
1 row in set (0.00 sec)
mysql> rollback to b; ## 回滚到保存点b
ERROR 1305 (42000): SAVEPOINT b does not exist
结论:从以上实验可以看出,回滚到a后,保存点b的数据就无法读取了,因为数据是保存在内存中的,如果回滚操作到某一个保存点之前的保存点,则在这个保存点之后的数据自动从内存中清除,所以会查询不到记录。