数据库基础

1.
什么是事务:
是访问数据库的一个操作序列,数据库通过一系列事务来存取数据。
事务特性ACID:
原子性:要么都执行,要么都不执行。
一致性:事物执行完成后数据库从一个一致状态到另一个一致状态。
隔离性:事物所做的操作在提交之前,对其他事物不可见。
永久性:事物一旦提交,对数据库做的改变会永久的存储在数据库中。

当事物串行执行,隔离性一定是可以满足的,只要满足原子性,就保证了一致性。

当事物并发执行,事物要满足原子性和隔离性才能保证一致性。

事物的持久话是为了应付数据库崩溃。

二、并发下的一致性问题

并发环境下由于隔离性难以保证而引发的一致性问题:
1.丢失更新。事物2覆盖了事物1的修改。
2. 脏读:读的数据还没有提交,如果回滚了,那么读到的数据就是无效的。
3.不可重复读:在一事务里,读同一数据读了两次,结果两次结果不一样。
4.幻读:在一个事务里面的操作中发现了未被操作的数据。比如就是在一个事务修改数据的时候,切换到了另一个事务B,B插入了一个数据,再切换到A的时候,A发现多了一个他没有修改过的数据。
 
脏读和幻读有点类似:脏读是其他事务修改了数据。幻读是其他事务新增了数据。
 
产生并发不一致主要是破坏了事物的隔离性。解决办法是通过并发控制解决隔离,并发控制可以通过封锁来实现,但是封锁需要用户自己控制。数据库管理系统提供了事物的隔离级别,让用户用更轻松的方式处理并发一致性问题。
 
三、封锁
封锁粒度
MySQL从锁的粒度来看可以分为:行级锁和表级锁。
尽可能锁的数量少,并发程度高。
但是加锁消耗资源,锁的粒度越小,系统开销越大。所以在选择的时候需要在锁的粒度和开销之间做权衡。
 
封锁类型
1.读写锁
 写锁又叫排他锁,读锁叫共享锁。
一个事物对数据对象A加了X锁,就可以对A进行读取和更新,加锁期间其他事物不能对A加任何锁。
一个事物对数据对象A加了S锁,就可以读取,其他事物也能加S。
2.意向锁
使用意向锁可以更容易的支持多粒度封锁。
一般一个事物想要对一张表加锁的时候,会先检查表上有没有其他锁,消耗一定的时间。
意向锁是指一个事务想要在表中的某个数据行上加X/S锁,关于加锁的规定是:
一个事务在获得某个数据行对象的S锁之前,必须先获得表的IS锁或更强的锁。
一个事务在获得某个数据行对象的X锁之前,必须先获得表的IX锁。
 
所以说,如果事物T想要对表A加X锁,任意的意向锁都是兼容的,毕竟只是想要对表加锁。

问题:如果两个IX,同时加锁了呢?

封锁协议

三级封锁协议
1.一级封锁协议
事务T要修改数据A时必须加X锁,直到T结束才释放。
解决丢失更新。
2.二级封锁协议
在一级的基础上,要求读数据A必须加上S锁,读完就释放,解决读脏数据。

如果不加读锁,很明显读出来脏数据了。

3.三级封锁协议

事务在读数据A时必须加S锁,直到事务结束了才释放S锁,在这期间就不能又其他事务对A加X锁,从而避免在读的期间数据发生改变。

乍一看好像二级和三级差不多,区别是:例如一个读取数据的事务T1前后读了两次,如果第一次读完就释放了,进来一个事务T2给他修改了,过了一会事务T1又进来了,这个时候读的就和第一次不一样了,所以三级是读事务到整个结束再释放。解决不可重复读。

两段锁协议

是指每个事务的执行可以分为加锁和解锁分两个阶段进行。
事务开始后就处于加锁阶段,一直到执行ROLLBACK和COMMIT之前都是加锁阶段。ROLLBACK和COMMIT使事务进入解锁阶段,即在ROLLBACK和COMMIT模块中DBMS释放所有封锁。
 
若并发执行的所有事务都遵循两段锁协议,那么这些事务的任何并发调度策略都是可串行化的。
可串行化指的是,通过并发控制,使得并发执行的事务结果u与某个串行执行的事务结果相同。
 
注意:注意两段锁协议和防止死锁的一次封锁法的异同之处。一次封锁法要求每个事务必须一次将所有要使用的数据全部加锁,否则就不能继续执行,因此一次封锁法遵守两段锁协议;但是两段锁协议并不要求事务必须一次将所有要使用的数据全部加锁,因此遵守两段锁协议的事务可能发生死锁。
 
MySQL隐式与显式锁定
MySQL的InnoDB存储引擎采用两段锁协议,会根据隔离级别在需要的时候自动加锁,并且所有的锁都是在同一时刻被释放,这被称为隐式锁定。
 
四、事务的隔离级别
隔离级别就是为了并发下的一致性问题,事务的隔离级别越高,在并发下产生的问题就越少,但付出的性能损耗也更大。一般有4种,但Spring有5种。
Spring默认的一种,如果spring配置事务时将isolation设置为这个值的话,那么将使用底层数据库的默认事务隔离级别。
1.读未提交(read uncommitted):事务中的修改,即使没有提交也可以读。可能导致脏、幻、不可重复。
2.读提交(read committed):读已经提交的数据。肯定没有脏读,可能导致幻、不可重复。Oracle默认
3.重复读(repeatable read): 在数据读出来之后加锁,读完这个事务也不结束,加了个锁,别的事务不可以改变这个记录,解决了脏读、不可重复。Mysql默认
4.可串行化(serializable):不管多少个事务,挨个运行完一个事务的所有子事务之后才可以允许别的事务的子事务。Oracle也支持。
一般就用读提交。

 

五、多版本并发控制

(首先为了理解mvcc作出补充)为了支持事务,InnoDB引入了下面几个概念:
redo log
redo log就是保存执行的SQL语句到一个指定的Log文件,当MySQL执行recovery时重新执行redo log记录的SQL操作即可。
undo log与redo log相反,undo log是为回滚而用,具体内容就是copy事务前的数据库内容(行)到undo buffer,在适合的时间把undo buffer中的内容刷新到磁盘。
rollback segment,回滚段这个概念来自Oracle的事务模型,在InnoDB中,undo log被划分为多个段,具体某行的undo log就保存在这个段中,
 
多版本并发控制(MVCC)是MySQL的InnoDB存储引擎实现隔离级别
 
 
参考https://www.cnblogs.com/xrq730/p/5087378.html 
https://github.com/CyC2018
posted @ 2019-02-27 16:08  这只鸟还不会飞翔  阅读(136)  评论(0编辑  收藏  举报