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

数据的完整性

完整性分类

具体描述

如何保证

实体完整性

每个实体都是独一无二的

主键 / 唯一索引(唯一约束)

参照完整性(引用完整性)

子表中不能有父表中没有的数据

外键

域完整性

数据都是有效的

数据类型和长度、非空约束、默认值约束、检查约束

数据的一致性:

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

事务的ACID特性:

事物的特性

描述

Atomicity(原子性)

不可分割

Consistency(一致性)

事务前后数据状态保持一致

Isolation(隔离性)

多个并发的事务不知道彼此的中间状态

Duration(持久性)

事务完成后,对数据的修改要持久化

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

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

如何解决这五类问题

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

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

事物的隔离级别

特点

read uncommitted

可以读到脏数据

read committed

Oracle默认的隔离级别 -不能避免不可重复读现象,但不会读到脏数据

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:
begin;
update 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:
begin;
update 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:
begin;
update tb_emp set sal=3800 where eno=1359;
commit;
事物B:
select * from tb_emp where sal<3000; --->还可以读到最开始使用select使用此命令读到的内容
commit;