事物的脏读、不可重复读取

it2022-05-05  258

事物: 是一种操作数据的机制,是数据库处理的最小工作单元 事物四个属性: 1、原子性:事物是一个独立的单元。一个事物中的若干语句是不可分割的(原子的)。 2、一致性:当事物结束时,数据必须处于一致状态。 3、持久性:事物结束之后,对于系统的影响是永久的。 4、隔离性:对数据进行操作的若干事物之间彼此隔离,也就是说,事物是独立的,一个事物的内部的操作不会依赖和影响其它事物。 事物并发产生的问题: 1、脏读取:一个事物更新了某数据但没有能够及时提交,而此时另一个事物读取了该数据,然后使用了该数据。 2、不可重复读取:一个事物对同一行数据重复读取两次,但是却得到了不同的结果。 3、更新丢失:不可重复读取的特例。 4、幻像读:事物在操作过程中进行两次查询,第二次查询的结果包含了第一次查询中未出现的数据(这里并不要求两次查询的SQL语句相同)。这是因为在两次查询过程中有另一个事物插入数据造成的。 设置事物隔离级别: 1、未提交读取(read uncommitted):允许脏读取,但不允许更新丢失。

--(cmder命令中) mysql> set autocommit=false;--设置事物提交方式 Query OK, 0 rows affected (0.00 sec) mysql> select @@autocommit from dual;--查询事物提交方式 +--------------+ | @@autocommit | +--------------+ | 0 | +--------------+ 1 row in set (0.00 sec) mysql> select @@tx_isolation from dual; --查询事物隔离级别 | @@tx_isolation | mysql> -----------+ | READ-UNCOMMITTED | --未提交读取 +------------------+- 1 row in set (0.02 sec) --cmder增加了数据未提交 mysql> insert into t_humans (id,name,birthdate) values (5,'周芷若','1404-2-23'); Query OK, 1 row affected (0.00 sec) mysql> select * from t_humans; +----+--------+--------+------------+---------+ | id | name | gender | birthdate | married | +----+--------+--------+------------+---------+ | 1 | 张三丰 | 男 | 1320-01-01 | N | | 2 | 张翠山 | 男 | 1380-05-18 | Y | | 3 | 张无忌 | 男 | 1403-03-23 | N | | 4 | 赵敏 | 女 | 1404-12-21 | N | | 5 | 周芷若 | NULL | 1404-02-23 | NULL | | 6 | 殷素素 | 女 | 1382-01-21 | Y | +----+--------+--------+------------+---------+ 6 rows in set (0.00 sec) --cmder 回滚事物 mysql> rollback; Query OK, 0 rows affected (0.00 sec) mysql> select * from t_humans; +----+--------+--------+------------+---------+ | id | name | gender | birthdate | married | +----+--------+--------+------------+---------+ | 1 | 张三丰 | 男 | 1320-01-01 | N | | 2 | 张翠山 | 男 | 1380-05-18 | Y | | 3 | 张无忌 | 男 | 1403-03-23 | N | | 4 | 赵敏 | 女 | 1404-12-21 | N | | 6 | 殷素素 | 女 | 1382-01-21 | Y | +----+--------+--------+------------+---------+ 5 rows in set (0.00 sec) --另一事物(cmd中) mysql> select @@autocommit from dual; +--------------+ | @@autocommit | +--------------+ | 0 | +--------------+ 1 row in set (0.00 sec) mysql> select @@tx_isolation from dual; +------------------+ | @@tx_isolation | +------------------+ | READ-UNCOMMITTED | +------------------+ 1 row in set (0.00 sec) --cmd读取了cmder未提交的数据 mysql> select * from t_humans; +----+--------+--------+------------+---------+ | id | name | gender | birthdate | married | +----+--------+--------+------------+---------+ | 1 | 张三丰 | 男 | 1320-01-01 | N | | 2 | 张翠山 | 男 | 1380-05-18 | Y | | 3 | 张无忌 | 男 | 1403-03-23 | N | | 4 | 赵敏 | 女 | 1404-12-21 | N | | 5 | 周芷若 | NULL | 1404-02-23 | NULL | --脏数据 | 6 | 殷素素 | 女 | 1382-01-21 | Y | +----+--------+--------+------------+---------+ 6 rows in set (0.00 sec) 总结:两个事物提交方式、隔离级别一致,cmd中的事物读取了cmder事物中未提交的数据(脏读)。

2、已提交读取(read committed):允许不可重复读取,但不允许脏读取。

--cmder命令中 mysql> select @@tx_isolation from dual; +----------------+ | @@tx_isolation | +----------------+ | READ-COMMITTED | +----------------+ mysql> delete from t_humans where id=5; Query OK, 1 row affected (0.04 sec) mysql> select * from t_humans; +----+--------+--------+------------+---------+ | id | name | gender | birthdate | married | +----+--------+--------+------------+---------+ | 1 | 张三丰 | 男 | 1320-01-01 | N | | 2 | 张翠山 | 男 | 1380-05-18 | Y | | 3 | 张无忌 | 男 | 1403-03-23 | N | | 4 | 赵敏 | 女 | 1404-12-21 | N | | 6 | 殷素素 | 女 | 1382-01-21 | Y | +----+--------+--------+------------+---------+ 6 rows in set (0.00 sec) mysql> commit; Query OK, 0 rows affected (0.17 sec) --cmd命令中 mysql> select @@tx_isolation from dual; +----------------+ | @@tx_isolation | +----------------+ | READ-COMMITTED | +----------------+ 1 row in set (0.00 sec) --cmd命令未修改数据前读取 --cmd命令修改数据后二次读取 mysql> select * from t_humans; mysql> select * from t_humans; +----+--------+--------+------------+---------+ +----+--------+--------+------------+---------+ | id | name | gender | birthdate | married | | id | name | gender | birthdate | married | +----+--------+--------+------------+---------+ +----+--------+--------+------------+---------+ | 1 | 张三丰 | 男 | 1320-01-01 | N | | 1 | 张三丰 | 男 | 1320-01-01 | N | | 2 | 张翠山 | 男 | 1380-05-18 | Y | | 2 | 张翠山 | 男 | 1380-05-18 | Y | | 3 | 张无忌 | 男 | 1403-03-23 | N | | 3 | 张无忌 | 男 | 1403-03-23 | N | | 4 | 赵敏 | 女 | 1404-12-21 | N | | 4 | 赵敏 | 女 | 1404-12-21 | N | | 5 | 周芷若 | 女 | 1342-11-21 | Y | | 6 | 殷素素 | 女 | 1382-01-21 | Y | | 6 | 殷素素 | 女 | 1382-01-21 | Y | +----+--------+--------+------------+---------+ +----+--------+--------+------------+---------+ 5 rows in set (0.00 sec) 6 rows in set (0.00 sec) 总结:cmd命令先读取数据,后cmder命令修改了该数据并提交,这时cmd命令再一次读取了该数据,得到与第一次查询**(数据不一致)**的问题,这就是不可重复读。

3、可重复读取(repeatable read):禁止不可重复读取和脏读,但是有可能出现幻影数据。 4、序列化(serializable):提供严格的事物隔离。它要求事物序列化执行,事物只能一个接着一个地执行,但不能并发执行。 说明:隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大,对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed,它能够避免脏读取,但是具有很好的并发性。 oracle中三命令: commit:提交事物后事物结束,默认状态下,新事物启动。 rollback:回滚事务,撤销事务中所有操作。 savepoint:执行过程中的标记点,可以配合rollback使用,使一个事物回滚到特定的保存点。 事物的的类型: 事物的执行分三个步骤: 1、开始事务 2、执行事务 3、结束事物 结束事物有两种情况: 1、提交事务 2、回顾事物

开启事务:Start Transaction事务结束:End Transaction提交事务:Commit Transaction回滚事务:Rollback Transaction事务开启的标志和结束的标志: 开启标志:

任何一条DML语句(insert、update、delete)执行,标志事务的开启 结束标志(提交或者回滚):

提交:成功的结束,将所有的DML语句操作历史记录和底层硬盘数据来一次同步

回滚:失败的结束,将所有的DML语句操作历史记录全部清空


目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。

候选码 若关系中的某一属性或属性组的值能唯一的标识一个元组,而其任何、子集都不能再标识,则称该属性组为(超级码)候选码。 例如:在学生实体中,“学号”是能唯一的区分学生实体的,同时又假设“姓名”、“班级”的属性组合足以区分学生实体,那么{学号}和{姓名,班级}都是(超级码)候选码。

第一范式:

定义:如果关系模式R的每个关系r的属性都是不可分的数据项,那么就称R是第一范式的模式。 简单的说,每一个属性都是原子项,不可分割。 name_age 张三 18

说明:这个就不符合第一范式 name | age 张三 | 18说明:这个符合第一范式(分成两个属性存储姓名、年龄)1NF是关系模式应具备的最起码的条件,如果数据库设计不能满足第一范式,就不称为关系型数据库。关系数据库设计研究的关系规范化是在1NF之上进行的。

第二范式:

定义:如果关系模式R是1NF,且每个非主属性完全函数依赖于候选键,那么就称R是第二范式。 简单的说,第二范式要满足以下的条件:首先要满足第一范式,其次每个非主属性要完全函数依赖与候选键,或者是主键。也就是说,每个非主属性是由整个主键函数决定的,而不能由主键的一部分来决定。

例如;订单只维护订单信息,不用关心用户和房间的具体信息,用户表只维护用户的信息,不涉及订单和房间的具体信息。房间表只维护房间表,不涉及用户和订单的具体信息。

第三范式:

定义:如果关系模式R是2NF,且关系模式R(U,F)中的所有非主属性对任何候选关键字都不存在传递依赖,则称关系R是属于第三范式。 简单的说,第三范式要满足以下的条件:首先要满足第二范式,其次非主属性之间不存在函数依赖。由于满足了第二范式,表示每个非主属性都函数依赖于主键。如果非主属性之间存在了函数依赖,就会存在传递依赖,这样就不满足第三范式。

总结: 第一范式在于列是否可以在分割,第二范式则要求一张表只能做一件事,把业务有没有拆分成多张表,第三范式是要求已拆分的表里只能存储另一个表的id(主键),而不能有其他信息,订单表里除了用户id还有用户name,这就破坏了第三范式。不会出现数据冗余、更新异常、删除、插入异常

范式的优点: 1、范式化的数据库更新起来更加快。 2、范式化后,只有很少的重复数据,只需要修改更少的数据; 3、范式化的表更小,可以在内存中执行; 4、很少的冗余数据,在查询的时候需要更少的distinct或者group by语句。 缺点:范式化的设计会产生更多的表,在查询的时候经常需要很多的表连接查询,导致查询性能下降。多表连接查询也能可能使一些索引策略无效,从而降低查询效率。 更加详细参考:https://blog.csdn.net/jdk_wangtaida/article/details/97019484 具体例子请参考:http://aijuans.iteye.com/blog/1629645 https://blog.csdn.net/qingking520/article/details/52937728


最新回复(0)