事务简介事务的核心是锁和并发,采用同步控制的方式保证并发的情况下性能尽可能高,且容易理解。这种方式的优势是方便理解;它的劣势是性能比较低。
计算机可以简单的理解为一个标准的打字机,尽管看起来计算机可以并行处理很多事情,但实际上每个CPU单位时间内只能做一件事,要么读取数据、要么计算数据、要么写入数据,所有的任务都可以看成这三件事的集合。计算机的这种特性引出了一个问题:当多个人去读、算、写操作时,如果不加访问控制,系统势必会产生冲突。而事务相当于在读、算、写操作之外增加了同步的模块,进而保证只有一个线程进入事务当中,而其他线程不会进入。
单个事务单元事务的四大特性分别是:原子型、一致性、隔离性和持久性。其中原子性指的是事务中包含的所有操作要么全做,要么全不做;一致性是指在事务开始以前,数据库处于一致性的状态,事务结束后,数据库也必须处于一致性的状态;隔离性要求系统必须保证事务不受其他并发执行的事务的影响;持久性是指一个事务一旦成功完成,它对数据库的改变必须是永久的,即使是在系统遇到故障的情况下也不会丢失,数据的重要性决定了事务的持久性的重要。
事务单元是通过Begin-Traction,然后Commit(Begin-Traction、Commit和Rollback之间所有针对数据的写入、读取的操作都应该添加同步访问),Begin和Commit之间就是一个同步的事务单元。例如,Bob给Smith 100块钱就是一个事务单元,这个过程中有很多步操作,具体如上图所示;但对业务来说,仅是一个转账的操作。
一组事务单元
当三个账户都在进行转账操作时,每个操作都涉及Smith账户,所有的事务都会排队,形成一组事务单元。
事务单元之间的Happen-Before关系中的四种可能性:读写、写读、读读、写写。所有事务之间的关系都可以抽象成这四种之一,来对应现在所有的业务逻辑处理。在此基础之上,需要用最快的速度处理多个事务单元之间的关系,同时还能保障这四种操作的逻辑顺序。
单个事务单元的其他例子除了转账操作是事务单元外,诸如商品要建立一个基于GMT_Modified的索引、从数据库中读取一行记录、向数据库中写入一行记录,同时更新这行记录的所有索引、删除整张表等都是一个事务单元。
事务单元的实现方式
Two Phase Lock(2PL)是数据库中非常重要的一个概念。数据库操作Insert、Update、Delete都是先读再写的操作,例如Insert操作是先读取数据,读取之后判读数据是否存在,如果不存在,则写入该数据,如果数据存在,则返回错误。假设在该场景下没有读操作,只是单纯写入数据,则数据本身并没有事务操作,Delete、Update操作与之类似。数据库利用这些操作的特性,在每一次查询过程中,只要查到数据,就会在该数据上加锁。理论上,所有被读取的数据都已加锁,不会再被其他人读到,也就是说对数据进行的中间操作状态对所有人都不可见,当所有中间状态完成后,提交操作时,解开锁,此时数据对所有系统可见,例如在转账过程中,所有人只能看到两种状态:开始时,A有钱,B没钱;结束时,B有钱,A没钱,而中间A减掉钱,B尚未加上钱的状态被锁隐藏掉了,这个操作就是数据库中处理事务的最标准的方式。如上图所示:事务中的Trx2(JoeLock)与其他事务不相关,因此可以并行执行;Trx1需要Lock两个数据Boblock和Smithlock,而Trx3同样需要Lock这两个数据,因此Trx3必须等待,且等待在Boblock上;Joe事务会先结束,Trx3会等到Trx1完成后才会开始。 |