捋捋思路,本章是一个总结,回答下前面的问题!
A:
Q1. UPDATE的行锁问题?
update操作时自带了行锁(写锁),只不过锁释放的时机会影响到并发事务时,是否发生的一系列问题(脏读、不可重复读、更新覆盖)
Q2. commit之前有所误解,事务提交和数据写入有所弄混(redo、undo、写入磁盘等)
- commit与修改数据持久化没关系,事务提交之前,有可能数据持久化到磁盘里;事务提交之后,数据也没有马上持久化到磁盘;
- wal:日志比数据先进行持久化操作。出现故障后,通过日志是否完全持久化(结束标志)判断是否进行数据的提交恢复(redo),还是根据undo日志进行回滚。
Q3. 由上述问题引发事务隔离与锁的问题
这里上述问题(脏读、不可重复读、更新覆盖)。
- RU(最低级,全都无法避免,一级封锁)
- RC(避免脏读,二级封锁) 事务更新数据上排他锁(事务结束才释放),共享锁读一下就释放(不可重复读)
- RR(无法避免幻读,三级封锁)读的时候上共享锁(直到事务结束才释放),三级封锁实现二阶段锁定(ACID)
- Serialization(事务串行化,最高级)解决了幻读,直接对 事务中 所 读取 或者 更改的数据所在的表加表锁(“范围锁”)
Q4. 二阶段锁定和那些事务执行中的锁 概念有所弄混
二阶段锁保证并发调度,实现事务的隔离性(事务开始获取锁,事务结束释放锁);如果事务都完完全全实现隔离性,没有并发,效率太低,所有就有了事务隔离等级,事务执行的锁(共享锁、排他锁)。
例如之前的RC级别,更新操作的时候上排他锁(直到事务结束释放),并不是事务一开始就获得(不满足二阶段锁定),造成了不可重复读、更新覆盖、幻读问题。
例如用SELECT FOR UPDATE(悲观锁,在查询的时候就上排他锁,防止其他事务获得该数据)解决更新覆盖。
三级封锁协议必定满足二阶段锁定
ps:二阶段锁定保证隔离性,二进制日志保证原子性
其他
三级封锁协议的死锁问题
进阶:repeatable read 导致死锁的情况(即便是 不同的资源在相同的顺序下获取)。 比如 事务1 读取 A,同时 事务2 也读取 A,那么事务1和事务2 同时对 A 上了共享锁,然后事务1 要UPDATE A,而此时 事务2 也要 UPDATE A,这个时候 事务1 等待 事务2 释放其在 A 上的共享锁,然后 事务2 要等待 事务1 释放其在 A 上的共享锁,这样,事务1 和 事务2 相互等待,产生死锁!(SQL Server/DB2 里面有 UPDATE LOCK 可以解决这种情况,具体的思路是,在 repeatable read 的情况下,将读取的数据 上的 UPDATE 锁,介于 共享锁 和 排他锁之间的一种锁,该锁的作用是 当出现上面这种情况后,事务1 和 事务2 对 A 上的是 UPDATE 锁,那么谁先 要修改 A,那么该事务就会将 UPDATE 锁可以顺利升级为 排他锁对该数据进行修改!)
网友评论