mysql事务和并发控制学习笔记
数据库保护
事务
什么叫事务
一段不可分割的sql语句的集合,要么全部发生,要么全部不发生。
事务的ACID特性
-
atomicity
-
原子性:事务的操作是不可分割的,要么全部发生,要么全部不发生。
-
isolation
-
隔离性主要是指多个事务并发执行时不能相互干扰。
-
durablity
-
持久性说的是事务一旦commit,那么这个操作对数据库的影响是持久性的,永久的。以后即便数据库发生了故障,事务的这种影响也不应该丢失。
-
consistency
-
一致性是指事务的执行使得数据库从一种一致性状态装换到另一种一致性状态。事务执行了,数据库的中数据仍然满足完整性约束,数据不会出错,关系不会增加或者丢失。满足了程序猿的预期,一致性是一种目的,而非手段,前面的三个特性满足了,一致性就达到了。
sql
-
start transaction
-
开始一个事务,mysql默认一条语句sql语句就是一个事务
-
commit
-
提交事务,事务的所有操作都已经完成,并且对数据库已经造成持久性的影响。注意,操作完成不一定代表事务完成,操作完成的输出结果可能还驻留在内存中,还没有写入外存。
-
rollback
-
回滚,当执行事务失败时,撤销事务已经执行的操作,就使得数据库恢复到执行事务前的状态。
数据库恢复技术
数据库的故障
-
事务内部故障
-
预期故障
-
程序员预先可以估计的到故障
-
非预期故障
-
-
系统故障
-
系统停止运转,要求系统重启的事件
-
介质故障
恢复技术
- 数据转储技术
-
静态转储
-
系统中没有事务在进行的时候进行转储,转储效率低
-
动态转储
-
动态转储是指转储期间允许对数据库进行存取和更新,效率高,但是不能保证副本和原数据一致。我们把转储期间事务对数据库的更改记录下来,通过副本和日志文件来恢复数据库的一致性。
-
海量转储
-
增量转储
-
- 登记日志技术
-
通过日志文件来记录每一事务队数据库的跟新活动,登记日志需要满足的条件
-
1.登记次序必须按照并发事务执行的时间顺序
-
2.必须先写日志文件,再写数据库。日志文件不要和数据库存在同一块物理磁盘上,需要定期跟换位置。
-
上面的问题中,某些redo操作可能是多余的,因为某些跟新操作已经对数据库造成了影响。我们引入检查点技术,一点的时间间隔设置一个检查点。
系统故障的恢复
1.正向扫描日志文件,找出已经执行过的事务,即含有start和commit记录的日志记录,加入redo队列。同时找出为执行成功的事务日志记录,即只有start的记录,加入undo队列
2.正向扫描redo队列里的每个记录,重现执行事务。
3.反向扫描undo队列的每个记录,撤销更新操作,即delete做insert操作,update做delete操作,insert做delete操纵。
事务内部故障的恢复
1.反向扫描日志文件,找到更新操作
2.若遇到update操作,则将“前像”写入数据库;遇到insert操作,则删除数据对象;若遇到delete操纵,则将数据对象插入数据库中。
3.继续反向扫描,找出跟新操作,执行同样的处理,知道遇到事务的开始标记start.
系统故障的恢复
利用后备副本和日志文件进行恢复
并发控制
为啥会引发问题
不同的事务队对同一数据对象至少执行一次写操作
并发操作引发的问题
-
丢失修改
-
不同事务多次修改一个数据对象
-
不可重复读
-
一个事务读取某个数据对象多次,结果不一致的现象,原因是某个事务在多次读取的中间时刻修改了这个数据对象。
-
读写冲突
-
幻读
-
幻读和不接重复读很类似,但是幻读读取的对象是数据的个数,比如表中字段个数,行数。读写冲突。
-
脏读
-
脏读是指读取到了错误的数据。
-
例如,事务A读取了还未提交的事务B的某个数据,之后事务B回滚了,这个数据就改变了,那么事务A就读取到了错误的数据。写读冲突。
串行化算法
如果有环则说明不可串行化。
无环则进行拓扑排序得到可串行化调度。
事务的隔离级别
是指一个事务与其他事务实现隔离的程度,是事务可接受的数据不一致的程度。较低的隔离级别可以增加并发,但是数据出错的风险就很高。
-
读未提交
-
不允许丢失修改,接受脏读和重复读
-
读已提交
-
不允许丢失修改和脏读,接受不可重复读。
-
可重复读
-
不允许丢失修改,读脏数据,重复读,接受幻影读。
-
可串行化
-
保证了可串行化,不允许丢失修改,脏读,重复读,幻影读
封锁技术
-
排他锁
-
若事务A数据对象加x锁,在A放锁前其他事务是不能修改此数据对象的。
-
共享锁
-
s锁,某事务A对数据对象加s锁,则事务A只能读A,不能改A,其他事务只能加S锁,不能加x锁,知道s锁被释放。
-
加锁方式
-
1.只允许在s锁上加s锁,其他不允许。如x锁上加s锁,x锁上加x锁,s锁上加x锁。
-
封锁协议
-
一级封锁协议
-
修改数据前必须加X锁,事务结束后释放,实现读未提交。但是对读没有要求,所以可能出现脏读和读不一致。
-
二级封锁协议
-
二级封锁协议是指在一级封锁协议的基础上,事务读取某个数据时,加s锁,不允许修改这个这个对象,读完就释放锁。避免了脏读。
-
三级封锁协议
-
在一级封锁协议的基础上,加上如果读某个数据则加锁,事务完成后放锁。这一点和二级协议有差别,这因为如此,三级封锁协议就能够实现读不一致。但是不能解决插入和删除的幻读现象。插入和删除是针对某个表而言,解决的办法就是对表或某个区域封锁。
-
两段锁协议
-
2PL协议,实现可串行化调度。
-
具备下列条件:
-
1.对任何对象读写操作之前都要上锁。
-
2.释放任意一个锁后,不允许再加锁。也就是说,加锁都应该在释放锁前完成。
-
满足2PL协议的事务一定可串行化的,但是可串行化不一定满足2PL协议。
-
死锁与活锁
活锁:两个或者两个以上的事务都在等待对方放锁,结果就是任何永远等待下去,这就叫死锁。
活锁:类似与操作系统中的饥饿,某个事务永远得不到数据对象。