数据库笔记(二)数据库的保护技术


数据库笔记(二)数据库的保护技术

一.安全性

 数据库的安全性主要指保护数据库,防止不合法的使用,以免数据的泄露,更改和破坏。

 在计算机系统中,安全措施是以一级一级层层设置的,安全模型如下图:

数据库笔记(二)数据库的保护技术

安全性控制方法:

        1.1用户标识和鉴别

                    禁止未经授权的用户对数据库操作,可利用身份认证,口令认证的方式标识用户。

        1.2用户存取权限控制

                    不同类型的用户拥有不同的权限。

        1.3视图机制

                    存取权限的控制的不仅可以通过授权实现,也可以通过定义用户的外模式来实现。

        1.4审计方法

                    审计是一种监视措施,把用户对数据库的所有操作记录下来放在审计日志中。

        1.5数据加密

                    数据加密是防止在存储和传输过程中失密的有效手段。

二.完整性

数据库的完整性是指数据库中数据的正确性和相容性,防止错误的数据进入数据库造成无效操作。

如月份只能用1~12来表示,否则就违反完整性;如一个学生不能有两个学号,否则就违反相容性。

常用来保证完整性的方法有约束和触发器两种。

约束:

1. 键码                   (primary key)      

用于唯一表示一个实体。

键码可以由多个属性构成,每个构成键码的属性称为码。

2. 单值约束              (unique)

某个属性的值是唯一的。

3. 引用完整性约束   (foreign key)

一个实体的属性引用的值在另一个实体的某个属性中存在。

4. 域约束                  (check )

某个属性的值在特定范围之内。

5. 一般约束              (check )

比如大小约束,数量约束。


触发器:

        触发器是当设定的事件发生时,由DBMS自动启动的维护程序数据库一致的程序。

        粒度: 行粒度(for each row) ,表粒度(for each statment)

        触发时间: 操作前(BEFORE),操作后(AFTER),取代操作(INSTEAD OF)

        触发操作:    删除(DELETE),插入(INSERT), 更新(UPDATE).


三.并发控制*(重点)

我们先来了解一下事务的概念:

    

数据库笔记(二)数据库的保护技术

事务指的是满足 ACID 特性的一系列操作。在数据库中,可以通过 Commit 提交一个事务,也可以使用 Rollback 进行回滚。在提交之前的所有操作就是一个事务,即使只有一条指令,或有很多条指令。

事务的四大特性(ACID)

1. 原子性(Atomicity)

事务被视为不可分割的最小单元,事务的所有操作要么全部提交成功,要么全部失败回滚。

2. 一致性(Consistency)

数据库在事务执行前后都保持一致性状态。在一致性状态下,所有事务对一个数据的读取结果都是相同的。

3. 隔离性(Isolation)

一个事务所做的修改在最终提交以前,对其它事务是不可见的。

4. 持久性(Durability)

一旦事务提交,则其所做的修改将会永远保存到数据库中。即使系统发生崩溃,事务执行的结果也不能丢失。可以通过数据库备份和恢复来保证持久性。

AUTOCOMMIT

MySQL 默认采用自动提交模式。也就是说,如果不显示使用START TRANSACTION语句来开始一个事务,那么每个查询都会被当做一个事务自动提交。


个人单独使用数据库是是不会出现问题的,但是如果同时有大于1个用户对数据库操作,那么事务之间可能会相互影响,从而产生错误。

问题 :并发不一致

1. 丢失修改

T1 和 T2 两个事务都对一个数据进行修改,T1 先修改,T2 随后修改,T2 的修改覆盖了 T1 的修改。

数据库笔记(二)数据库的保护技术

2. 读脏数据

T1 修改一个数据,T2 随后读取这个数据。如果 T1 撤销了这次修改,那么 T2 读取的数据是脏数据。

数据库笔记(二)数据库的保护技术

3. 不可重复读

T2 读取一个数据,T1 对该数据做了修改。如果 T2 再次读取这个数据,此时读取的结果和第一次读取的结果不同。

数据库笔记(二)数据库的保护技术

4. 幻影读

T1 读取某个范围的数据,T2 在这个范围内插入新的数据,T1 再次读取这个范围的数据,此时读取的结果和和第一次读取的结果不同。

数据库笔记(二)数据库的保护技术

解决方法

产生并发不一致性问题主要原因是破坏了事务的隔离性,解决方法是通过并发控制来保证隔离性。

在没有并发的情况下,事务以串行的方式执行,互不干扰,因此可以保证隔离性。在并发的情况下,如果能通过并发控制,让事务的执行结果和某一个串行执行的结果相同,就认为事务的执行结果满足隔离性要求,也就是说是正确的。把这种事务执行方式称为 可串行化调度 。

并发控制可以通过封锁来实现,但是封锁操作需要用户自己控制,相当复杂。数据库管理系统提供了事务的隔离级别,让用户以一种更轻松的方式处理并发一致性问题。


下面是一些关于锁的知识:

封锁粒度

数据库笔记(二)数据库的保护技术

MySQL 中提供了两种封锁粒度:行级锁以及表级锁。

应该尽量只锁定需要修改的那部分数据,而不是所有的资源。锁定的数据量越少,发生锁争用的可能就越小,系统的并发程度就越高。

但是加锁需要消耗资源,锁的各种操作,包括获取锁,检查锁是否已经解除、释放锁,都会增加系统开销。因此封锁粒度越小,系统开销就越大。

在选择封锁粒度时,需要在锁开销和并发程度之间做一个权衡。

封锁类型

1. 读写锁

  • 排它锁(Exclusive),简写为 X 锁,又称写锁。
  • 共享锁(Shared),简写为 S 锁,又称读锁。

有以下两个规定:

  1. 一个事务对数据对象 A 加了 X 锁,就可以对 A 进行读取和更新。加锁期间其它事务不能对 A 加任何锁。
  2. 一个事务对数据对象 A 加了 S 锁,可以对 A 进行读取操作,但是不能进行更新操作。加锁期间其它事务能对 A 加 S 锁,但是不能加 X 锁。

锁的兼容关系如下:

- X S
X NO NO
S NO YES

2. 意向锁

使用意向锁(Intention Locks)可以更容易地支持多粒度封锁。

在存在行级锁和表级锁的情况下,事务 T 想要对表 A 加 X 锁,就需要先检测是否有其它事务对表 A 或者表 A 中的任意一行加了锁,那么就需要对表 A 的每一行都检测一次,这是非常耗时的。

意向锁在原来的 X/S 锁之上引入了 IX/IS,IX/IS 都是表锁,用来表示一个事务想要在表中的某个数据行上加 X 锁或 S 锁。有以下两个规定:

  1. 一个事务在获得某个数据行对象的 S 锁之前,必须先获得表的 IS 锁或者更强的锁;
  2. 一个事务在获得某个数据行对象的 X 锁之前,必须先获得表的 IX 锁。

通过引入意向锁,事务 T 想要对表 A 加 X 锁,只需要先检测是否有其它事务对表 A 加了 X/IX/S/IS 锁,如果加了就表示有其它事务正在使用这个表或者表中某一行的锁,因此事务 T 加 X 锁失败。

各种锁的兼容关系如下:

- X IX S IS
X NO NO NO NO
IX NO YES NO YES
S NO NO YES YES
IS NO NO YES YES


任意 IS/IX 锁之间都是兼容的,因为它们只是表示想要对表加锁,而不是真正加锁;
解释如下:

  • S 锁只与 S 锁和 IS 锁兼容,也就是说事务 T 想要对数据行加 S 锁,其它事务可以已经获得对表或者表中的行的 S 锁。


简单的对数据加锁并不能保证数据的一致性。在对数据加锁时,还需要约定一些规则,比如何时申请,持锁时间,何时释放,这些规则成为封锁协议。封锁协议分三级。解决不同程度的问题。

封锁协议

1. 三级封锁协议

一级封锁协议

事务 T 要修改数据 A 时必须加 X 锁,直到 T 结束才释放锁。

可以解决丢失修改问题,因为不能同时有两个事务对同一个数据进行修改,那么一个事务的修改就不会被覆盖。

T1 T1
lock-x(A)  
read A=20  
  lock-x(A)
  wait
write A=19 .
commit .
unlock-x(A) .
  obtain
  read A=19
  write A=21
  commit
  unlock-x(A)


在一级的基础上,要求读取数据 A 时必须加 S 锁,读取完马上释放 S 锁。二级封锁协议

可以解决读脏数据问题,因为如果一个事务在对数据 A 进行修改,根据 1 级封锁协议,会加 X 锁,那么就不能再加 S 锁了,也就是不会读入数据。

T1 T1
lock-x(A)  
read A=20  
write A=19  
  lock-s(A)
  wait
rollback .
A=20 .
unlock-x(A) .
  obtain
  read A=20
  commit
  unlock-s(A)


在二级的基础上,要求读取数据 A 时必须加 S 锁,直到事务结束了才能释放 S 锁。三级封锁协议

可以解决不可重复读的问题,因为读 A 时,其它事务不能对 A 加 X 锁,从而避免了在读的期间数据发生改变。

T1 T1
lock-s(A)  
read A=20  
  lock-x(A)
  wait
read A=20 .
commit .
unlock-s(A) .
  obtain
  read A=20
  write A=19
  commit
  unlock-X(A)


调度是指多个事务的某个执行顺序。DBMS对并发事务不同的调度产生不同的结果,但是串行调度是肯定正确的。可串行调度是并发事务正确性的准则。而事务遵循两段锁协议是保证并发操作可串行化调度的充分条件。

2. 两段锁协议


加锁和解锁分为两个阶段进行。事务 T 对数据 A 进行读或者写操作之前,必须先获得对 A 的封锁,并且在释放一个封锁之后,T 不能再获得任何的其它锁。

例如以下操作满足两段锁协议,它是可串行化调度。

lock-x(A)...lock-s(B)...lock-s(C)...unlock(A)...unlock(C)...unlock(B)

但不是必要条件,例如以下操作不满足两段锁协议,但是它还是可串行化调度。

lock-x(A)...unlock(A)...lock-s(B)...unlock(B)...lock-s(C)...unlock(C)

3.两段锁协议与三机协议的区别:

     两段锁协议与三级协议是两类目的不同的协议,两段锁是保证并发调度的正确性。三级锁协议是在不同程度上保证数据的一致性。遵守第三级封锁协议必然遵守两段锁协议,即三级封锁协议是两段锁协议的前提。


四.故障恢复

            

           数据库恢复技术的基本原理是冗余,利用存储在其他地方的冗余数据,来重建数据库张已被破坏或不正确的那部分数据。

           关键的两个问题是:如何建立冗余数据和如何利用冗余数据进行数据库恢复。           

       

           建立冗余数据:

                1.数据备份

                2.日志文件

        数据库恢复策略:

恢复方法(正向扫描文件日志) 

1. Undo 故障发生时未完成的事务(撤销) 

2. Redo 已完成的事务(重做)

但是若全部扫描日志文件,会浪费大量时间,所以一般都是设置检查点。

下图展示了,在不同时刻不同状态的

                 数据库笔记(二)数据库的保护技术



参考:https://github.com/CyC2018/Interview-Notebook     //这个建议大家看看。写的很好。

          刘爽英《数据库原理及应用》

          郑晓霞 《数据库原理及新技术研究》