Bootstrap

关系型数据库保证数据完整性和一致性的方法

对于数据库来说,关系型数据库对于保证数据完整性和一致性方面表现是最好的!

数据的完整性

完整性分类具体描述如何保证
实体完整性每个实体都是独一无二的主键 / 唯一索引(唯一约束)
参照完整性(引用完整性)子表中不能有父表中没有的数据外键
域完整性数据都是有效的数据类型和长度、非空约束、默认值约束、检查约束

数据的一致性:

数据的一致性通过事务实现 —> 一系列的对数据进行的不可分割的操作,要么全做,要么全部做

事务的ACID特性:

事物的特性描述
Atomicity(原子性)不可分割
Consistency(一致性)事务前后数据状态保持一致
Isolation(隔离性)多个并发的事务不知道彼此的中间状态
Duration(持久性)事务完成后,对数据的修改要持久化

并发事务访问数据可能产生五大类的问题:

  • 第一类丢失更新
  • 第二类丢失更新
  • 脏读(读脏数据)
  • 不可重复读
  • 幻读

如何解决这五类问题

  • 单版本并发控制 - 锁 - 悲观锁 - 性能太差
  • 多版本并发控制(MVCC)- 乐观锁 - 性能更好 - 需要冗余字段来支持

直接操作锁非常的麻烦,我们可以通过设置事务隔离级别的方式,让数据库自动选择合适的锁机制来保护数据。

事物的隔离级别特点
read uncommitted可以读到脏数据
read committedOracle默认的隔离级别 -不能避免不可重复读现象,但不会读到脏数据
repeatable read避免不可重复读现象( MySQL默认的事物隔离级别) 另一个事物更新数据,刚才查到的是什么,现在还是什么(查询事物没有提交和回滚之前都可以重复读)
serializable此种方法不会出现并发数据的问题,但是效率地下,不建议使用

MySQL如何查看和修改事务隔离级别(transaction —> tx)

功能方法
查看事物隔离级别select @@tx_isolation
修改事物隔离级别set session transaction isolation level read committed

在Linux环境下验证不同事物隔离级别的特性所需要使用到的命令

事物过程相关命令
开事物begin; / start transaction;
提交事物commit;
回滚事物rollback;(未提交之前,取消前面的操作,如更新或删除操作)

linux下面验证的场景举例:
数据库连接:mysql -u root -p

第一个实验场景:读脏数据

事物A:
beginupdate tb_emp set sal=2800 where eno = 1359;
事物B:
set session transaction isolation level read committed;
begin;
select * from tb_emp;       --->读脏数据
commit;
事物A:
rollback;

第二个实验场景:不可重复读

事物B:
set session transaction isolation level read committed;
begin;
select * from tb_emp where sal<3000;
事物A:
beginupdate tb_emp set sal=3800 where eno=1359;
commit;
事物B:
select * from tb_emp where sal<3000; --->没有1359对应的记录了,不可重复读
commit

第三个实验场景:可以重复读

事物B:
set session transaction isolation level repeatable read;
begin;
select * from tb_emp where sal<3000;
事物A:
beginupdate tb_emp set sal=3800 where eno=1359;
commit;
事物B:
select * from tb_emp where sal<3000; --->还可以读到最开始使用select使用此命令读到的内容
commit
;