疫情严重,闲着无聊,从书架中找出大学的书看看,正所谓温故而知新,可以为师矣。做个笔记。
数据库的管理
1.事务的概念
1.1事务的定义
事务(transaction)是构成单一逻辑工作单元的操作集合。在程序中,事务以BEGIN TRANSCATION语句开始,以COMMIT语句或者ROLLBACK语句结束。事务的意义在于把一组操作集合当成一个整体,要么全做,要么不做,决不允许只做一半的操作。
1.2事务的ACID性质
1.原子性(atomicity)
一个事务对数据库的所有操坐,是一个不可分割的工作单元。
2.一致性(consistency)
一直事务独立执行的结果,应保持数据库的一致性,即数据不会因为事务的执行而遭受破坏。
3.隔离性
在多个事务并发执行时,系统应保证与这些事务先后独立执行时的结果一样,此时称事务达到了隔离性的要求。也就是在多个事务并发执行时,保证执行结果是正确的,如同单用户环境一样。隔离性是有DBMS的并发控制子系统实现的。
4.持久性
一个事务一旦完成全部操作后,它对数据库的所有更新应永久的反应在数据库中,不会丢失。
2.数据库的并发控制
数据库的并发操作通常会带来3个问题:丢失更新、读脏数据、不一致分析(不可重复读)。
2.1更新丢失
两个事务同时对一条记录操作引起。例如:事务T1将记录A+50,事务T2将记录A*2。如果初始值是100,并发的情况下,都是已后执行的为准,前面那条更新的记录丢失了一样,称为更新丢失问题。
2.2读脏数据问题
事务T1把A的值修改为70,但尚未提交(COMMIT),事务T2紧跟着读取未提交的A值。随后,事务T1做ROLLBACK操作,把A恢复成100。而事务T2仍在使用被撤销了的值A70。在数据库中,把未提交的随后被撤销的数据称为“脏数据”
2.3不一致分析问题(不可重复读)
事务T读取数据后,另一个事务执行更新操作,使事务T再次读取结果时,前后不一致的问题。一般有3种现象
- 得到与前一次不同的值
- 发现某些数据消失了
- 发现多了一些数据
解决并发操作的问题一般有两种技术:封锁(Locking)和时标(TimeStamping)。大多数采用封锁技术。
封锁技术中分两种,排他和共享锁。
1.排他型锁(X锁,又称写锁)
事务T对某个数据(可以是数据项,记录,数据集乃至整个数据库)实现X锁,那么其他事务要等T解锁以后,才能对这个数据进行封锁。
px协议。使用X锁的规则称为PX协议。其主要内容:任何企图更新记录R的事务必须先执行“XFIND R”操作,以获取对R的X锁,才能读或者写记录R;如果未获取X锁,该事务进入等待状态。直到获取。
pxc协议。在一个事务对数据加上X锁,并且对数据进行修改后,如果过早地解锁,有可能引起其他事务读了未提交的数据,引起丢失更新问题。为了解决这一问题,X锁的解除应该唉事务结束(COMMIT或ROLLBACK)操作中。
2.共享型锁(S锁,读锁)
采用X锁的并发控制并发程度低,只允许一个事务独锁数据。而其他事务只能等待。为此还引入了共享锁,称为读锁。
如果事务T对某数据加上S锁后,仍允许其他事务再对该数据添加S锁,但在对该数据的所有S锁都解除之前,绝不允许任何事务对该数据加X锁。(有S锁不让加X锁)
使用S锁的规则,简称PS协议。
像PXC一样,PSC协议的要点“S锁的解除应该合并到事务的结束操作中”
PXC解决更新丢失问题。PSC解决读脏数据和不可重复读问题。
采用封锁技术,解决并发操作引起的问题,但有可能产生新的问题:活锁、饿死和死锁。
1.活锁问题
系统可能是某一个事务永远处于等待状态,得不到封锁机会。解决活锁的一个简单办法采用“先来先服务”。如果事务有优先级,那么优先级低的可能永远等不到,此时可采用升级的方式,等待一段时间后,提高优先级,等待封锁。
2.饿死问题
可能存在一个事务序列,每个事务都申请S锁,如果有一个事务想要加X锁,那么永远没有机会封锁。可以使用一下方式解决
事务T2申请S锁时,还需要条件:
- 不存在在数据Q上持有X锁的其他事务;
- 不存在等待数据Q加锁且先于事务T2的申请加锁的事务。
3.死锁
两个或者两个以上事务都处于等待状态。并且每个事务都在等待其他另一个事务解除封锁,才能继续执行,这就造成了任何一个事务都无法继续执行。
3.可串行化
事务的执行顺序称为“调度”。在每个事务中,语句的先后顺序在各种调度中始终保持一致。在这个前提下,如果一个并发调度的执行结果与某一串行调度的执行结果等价,那么这个并发调度称为“可串行化的调度”。
4.事务的隔离级别
1.可以读取为提交的数据(READ UNCOMMITTED)
脏读问题。读取到未提交事务,其他事务ROLLBACK后,读取到的数据就成了脏数据。
2.读取提交数据(READ COMMITTED)
有不可重复读的问题。同一个事务,相同的sql,执行的结果不一致。数据被修改,称为不可重复读。
3.可重复读(REPEATABLE READ,mysql默认级别)
只允许事务读一提交的数据,并且在两次读同一数据时不允许其他事务修改次数据。
可能引起“幻读”,多一些数据或者少一些数据。在同一事务中,执行两次相同的 sql,得到的条数不一致,可能多一条,可能少一条。(不可重复的和幻读十分相似,区别在于,不可重复读是数据被修改了,幻读是数据多了少了。)
4.可串行化
允许事务和其他事务并发执行,但系统必须保证并发调度时刻串行化。简单的处理是,对表添加写锁,解决“幻读”问题,但这有个问题,降低并发能力,这种隔离过于严格,较少设置成可串行化。