并发控制、事务
事务是用户定义的一个数据库操作序列,这些操作要么全做要么全不做。
程序和事务的区别
事务是恢复和并发控制的基本单位
一个应用程序通常有多个事务组成
定义事务的两种方式
显式方式:事务开始由用户显示控制或DBMS自动隐含,事务结束由用户显示控制
隐式方式:当用户没有显示的定义事务时,由DBMS自动划分事务
事务的ACID特性
原子性:事务是一个不可分割的整体,要么全做,要么全不做
一致性:事务的执行结果必须使数据库从一个对各个用户一致的状态,到另一个一致的状态。
一致性与原子性密切相关
持续性:一个事务一旦提交,它对数据的改变是永久性的。
隔离性(重要):一个事务的执行不能被另一个事务干扰,一个事务内部的操作及使用的数据对其他并发事务是隔离的。
事务隔离级别
Read Uncommitted(读取未提交内容):所有事务都可以看到其他未提交事务的内容。读取未提交的数据,也被称之为脏读(Dirty Read)
Read Committed(读取提交内容):一个事务只能看见其他事务已经提交的内容,可能造成不可重复读
Repeatable Read(可重读):一个事务多次读取数据,并且在读取数据期间本事务不修改数据的情况下,是相同的
Serializable(可串行化):这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每
个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
不可重复读:指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了
脏读(Dirty Read):读取未提交的数据,
幻读:当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。
脏数据:与数据库中的数据不一致,不正确的数据
事务语句
事务开始: begin transaction
事务结束提交: commit
事务回滚:rollback
锁机制
锁:就是事务A在对某个数据进行操作之前,先向系统发出请求,对其加锁,之后在事务A对该数据有了一定的控制,在事务A释放锁之前,其他事务不
能对此数据进行操作
锁的类型
排它锁(X锁):又称为写锁,若事务A对数据对象加了x锁,则此数据对象只能被事务A读取、修改。直到A释放数据对象上的锁
共享锁(Y锁):又称为读锁,若事务A对数据对象加了y锁,则其他事务只能再此数据对象上加Y锁,直到A释放数据对象上的锁
相容性:不相容:X\X,X\S,S\X
相容:S\S
封锁粒度:可以是逻辑单元,也可以是物理单元
逻辑单元:整个数据库、列、行、关系、索引等
物理单元:页、块
锁协议:
一级锁协议:事务在修改数据之前,必须先对数据加X锁,直到事务结束才释放。
在一级协议中,若不对事务进行修改,仅仅读数据是不需要加锁的
二级锁协议:一级锁协议加上事务在读取数据之前必须先对其加s锁,读完后立即释放s锁
三级锁协议:一级锁协议加上事务在读取数据之前必须先对其加s锁,直到事务结束才释放
两段锁协议:两段锁协议是指每个事务的执行可以分为两个阶段:生长阶段(加锁阶段)和衰退阶段(解锁阶段)。
加锁阶段:在该阶段可以进行加锁操作。在对任何数据进行读操作之前要申请并获得S锁,在进行写操作之前要申请并获得X锁。
加锁不成功,则事务进入等待状态,直到加锁成功才继续执行。
解锁阶段:当事务释放了一个封锁以后,事务进入解锁阶段,在该阶段只能进行解锁操作不能再进行加锁操作。
两段封锁法可以这样来实现:事务开始后就处于加锁阶段,一直到执行ROLLBACK和COMMIT之前都是加锁阶段。ROLLBACK和COMMIT使事务
进入解锁阶段,即在ROLLBACK和COMMIT模块中DBMS释放所有封锁
活锁:活锁指的是任务或者执行者没有被阻塞,由于某些条件没有满足,导致一直重复尝试,失败,尝试,失败。 如:
如果事务T1封锁了数据R,事务T2又请求封锁R,于是T2等待。T3也请求封锁R,当T1释放了R上的封锁后,系统首先批准了T3的请求,T2仍然
等待。然后T4又请求封锁R,当T3释放了R上的封锁之后,系统又批准了T4的请求......T2可能永远等待
死锁:死锁指两个或两个进程,由于竞争资源,而产生的相互阻塞的状态。若无外力的作用无法解开。
活锁和死锁的区别在于,处于活锁的实体是在不断的改变状态,所谓的“活”, 而处于死锁的实体表现为等待;活锁有可能自行解开,死锁则不能。
死锁的预防:一次封锁法、顺序封锁法