事务的基本概念
事务是用户定义的一个数据库操作序列,这些操作要么全做,要么全不做,是一个不可分割的工作单位
事务的四大特性
- 原子性:数据库包括的诸多操作要么全做,要么全不做,如果某部分成功,那么将进行回滚,不会对数据库造成任何影响
- 一致性:事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。如 初始 A 100 ,B 100 ,A转50给B,则 A 50 吧150 A的钱加上B的钱始终是 200
- 隔离性:一个事务的执行不能被其他事务干扰。即一个事务内部操作及使用的数据对其他事务是个例的,并发执行的各个事务之间不能有任何干扰
- 持久性:一个事务一旦提交,它对数据库中数据的改变就应该是永久性的了,接下来的其他操作或故障不应该对其执行结果有任何影响
并发执行带来的问题
- 丢失修改:两个事务T1和T2读入同一数据并进行修改,T1事务的提交结果破坏了T1提交的结果,导致了T1的修改丢失
- 脏读:事务T1修改某一数据并将其写回磁盘,事务T2读取了这一数据后,T1因为某些原因回滚了。T2读取到了T1未提交的数据,与数据库当前数据不一致。
- 不可重复读:T1读取某一个数据后,T2进行了修改,T1再次读取得到了与前一次不同的值。
- 幻读:T1先查看了数据库的行数 10行然后对其进行了 数据变 0 操作,这时候T2插入了几条数据,T1再次查看时发现,怎么多了几条数据,就跟幻觉一样。
Mysql数据库提供的4种隔离级别
- Read uncommitted (读未提交):最低级别,都不能保证
- Read committed (读已提交):可避免脏读的发生。
- Repeatable read (可重复读):可避免脏读、不可重复读的发生。
- Serializable (串行化):可避免脏读、不可重复读、幻读的发生。
并发控制的主要技术
- 封锁
- 时间戳
- 乐观控制法
- 多版本并发控制
下边主要谈谈封锁相关
封锁
事务对对象进行操作的时候,先向系统发出请求,对其枷锁,加锁后才能进行相应操作
- 排他锁:也称写锁,X锁,就像它的名字一样,事务T对对象A加了X锁,其他事务将不能对A加任何类型的锁,保证了在T事务释放锁之前,其他事务不能读取和修改A
- 共享锁:也称读锁,S锁,事务T对对象A加上了S锁,则允许T可以读A但是不能修改A,其他事务能再次对A加上S锁,却不能加S锁,直到T释放A上的S锁。
封锁协议
- 一级封锁协议:事务T修改A之前先对其加上X锁,事务结束才释放
- 二级封锁协议:事务T读取A之前,对其加上S锁,读取结束就释放
- 三级封锁协议:事务T读取A之前,对其加上S锁,事务结束才释放
- 注意:二级封锁协议,以及三级封锁协议都是建立在一级封锁协议之上的
活锁
比如事务T1封锁数据A,事务T2又请求封锁数据A,于是T2等待,T3也请求封锁数据A,当T1释放时,系统首先批准了T3,T2等待,然后又是T4,T5…这样下去T2将会一直等待
避免活锁的方法就是先来先服务。
死锁
T1封锁了数据A,T2封锁了数据B,T1又请求封锁数据B,T2已经封锁了数据B,所以T1等待,接下来T2又申请封锁数据A,T1封锁了数据A,就这样永远等待下去。
防止死锁时可以使用 一次封锁法,顺序封锁法,这是操作系统比较广泛的,数据库一般使用的时死锁的诊断与解除
死锁的诊断与解除
- 超时法
- 如果一个事务超过了规定的时限,就认为发生了死锁,这个方法容易实现但是很有可能误判。
- 等待图法
事务等待图时一个有向图,形成了环则发生了死锁,
解除死锁:选择一个处理死锁代价最小的事务,将其撤销,释放该事务的所有的锁,使其它事务继续运行下去。