欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

一篇文章看懂事务的一致性

程序员文章站 2024-01-11 15:24:40
...

一、前言

    事务一直以来是一个玄之又玄的东西,非常难以理解。难以理解倒不是因为事务本身有多难,而是事务这个概念被各种刻意包装,以至于让人晕头转向,摸不着头脑。例如各种抽象的概念,一致性、持久性、原子性、持久性、读未提交、读已提交、可重复读、序列化,Spring也抽象了事务的传播属性,数据库本身又有各种锁,于是我们就晕头了。今天我们就来扒一扒事务,看看事务华丽外衣下的本质。本篇博客结合沈询的分享,加上自己的一些总结。

二、事务要解的最终问题——“一致性”

    一致性是一个名词,其实这里实际上应该当成一个动词来理解,多个参与者达成一致,达成了共识,相互之间不扯皮。这样说可能比较抽象,举个生活中的例子。

     一天,老王和老王老婆,同时去银行取钱,老王查了银行卡账号有1w块钱,于是取了出来,假设老王老婆和老王同时查询,也看到有1w块钱,于是点击取款,最后发现没钱可取了,于是要扯皮了,这就不一致了。

    用一句通俗的话来描述事务的一致性:所有事务的参与方,眼所见,便是心所得。上面的例子中,老王老婆看到了卡上有1w,却没法取,于是就要扯皮了。这就是严苛的一致性所定义的内容。

    下面我们来具体分析一下上面的例子。

    首先引出事务单位的概念,事务单元就是完成一个具体的业务的最小单元,上面的例子中包含两个事务单元。按照正常的时间线,要想不扯皮,应该看到如下执行顺序。

    一篇文章看懂事务的一致性

        但是扯皮的事情发生了,两个事务单元并行了,于是出现如下的执行顺序。事务单元二左移,与事务单元一并行。

    一篇文章看懂事务的一致性

    上面的场景似曾相识,其实就是和线程安全所描述的内容一摸一样,《一篇文章看懂Java并发和线程安全》,要想不扯皮,必须让访问的共享资源互斥,用Java代码可以描述成如下的代码:

public class Consistency {

	public static void main(String[] args) {
		ReentrantLock lock = new ReentrantLock();
		lock.lock();
		try {
			int balance = query();// 查询余额
			if (balance > 0) {
				drawingOutCash();// 取出现金
			}
		} catch (Exception e) {

		} finally {
			lock.unlock();
		}
	}
}

   要想强一致,所有的事务单元串行着执行,这就是事务隔离级别中的SERIALIZABLE,于是就引出了事务的隔离级别。

三、事务的隔离级别

    强一致,必须让所有事物单元串行执行,这便是隔离级别中的SERIALIZABLE(序列化),但是这样系统的性能是可想而知的,几乎不可用,于是需要放宽对锁的要求,所以出现了其他的隔离级别。事务的隔离级别是以性能为由对一致性的破坏,它的出现是为了破坏一致性,而不是维持一致性。

    事务单元与事务单元的关系只有四种:读读、读写、写读、写写

    SERIALIZABLE(序列化)

    一篇文章看懂事务的一致性

    要想进一步提升性能,于是出现了读写锁,这里就出现了两种隔离级别:REPEATABLE_READ(可重复读)和READ_COMMITED(读已提交)

    REPEATABLE_READ(可重复读):

    读锁不能被升级为写锁,那么对共享资源的写,就进不来,这样“读读”是可并行的,这样会出现幻读,因为在这个级别,表是不会被看做是共享资源的,所以可以insert

    一篇文章看懂事务的一致性

    READ_COMMITED(读已提交):

    读锁可以被升级为写锁,那么当对共享资源正在读时,可以被写请求升级为写锁,那么这样“读读”、“读写”可以并行,于是出现了幻读、不可重复读等等现象

    一篇文章看懂事务的一致性

    READ_UNCOMMITTED

    只加写锁,读不用申请锁,这样“读读”、“读写”、“写读”都可以并行,但“写写”还不能并行,于是所有的写都是串行,于是就有了脏读、不可重复读、幻读等等。

    一篇文章看懂事务的一致性

    这就是事务隔离级别的真相,事务隔离级别越低,并行度越好,一致性越低。

四、一句话总结

    事务的一致性和线程安全所面对的问题一模一样,要想维持一致性,需要保证两点:共享变量的可见性、临界区代码访问的顺序性。

 

快乐源于分享。

   此博客乃作者原创, 转载请注明出处