PHP,DDD,CQRS,Event Sourcing,Kubernetes,Docker,Golang

0%

了解mysql事务

mysql事务可能大多数人都有所了解,本篇博文主要记录我了解的事务的一些细节之处,也必然对事务能有进一步的理解。 看过《高性能mysql》一书,上面写道事务就是一组原子性的sql查询,或者说一个独立的工作单元。可能这句话并不是那么好理解,什么叫原子性?什么又是独立的工作单元?看几个例子和几个名词解释或许更加有帮助。

在事务中,如果数据库引擎能够成功地对数据库应用一组查询的全部语句,那么就执行这组查询。如果其中有任何一条语句因为崩溃或其他原因无法执行,那么所有的语句都不会执行。也就是说,事务内的语句,要么全部执行成功,要么全部执行失败。 讲解事务最经典的例子还是银行转帐。

假设银行的数据库有两张表:支票表和储蓄表,现在要从用户A的支票账户转义200元到他的储蓄帐户,那么至少需要三个步骤

1
2
3
1、检查支票账户的余额高于200元。
2、从支票账户余额中减去200元。
3、在储蓄帐户余额中增加200元。

上面三个步骤操作必须打包在一个事务中,其中任何一个步骤失败,则必须回滚所有步骤,即之前操作的几个步骤都失效。 一般可以用START TRANSACTION语句开始一个事务,然后要么使用COMMIT提交事务将修改的数据持久保留,要么使用ROLLBACK撤销所有的修改。上面三个步骤用语句可以这样表示:

1
2
3
4
5
1、START TRANSACTION; 
2、SELECT balance FROM checking WHERE customer_id=123123;
3、UPDATE checking SET balance = balance -200 WHERE customer_id=123123;
4、UPDATE savings SET balance = =balance + 200 WHERE customer_id=123123;
5、COMMIT;

单纯的讲事务还是不够的。试想一下,如果执行到第四条语句时服务器崩溃了,会发生什么?用户可能会损失200元。再假如,在执行到第三条语句和第四条语句之间时,另一个进程要删除支票账户的所有余额,那么结果可能就是银行在不知情的状况下白了用户200元。 由此看来空谈事务还是不够的,需要通过严格的ACID测试,一个运作良好的事务系统必须具备四个特性,即ACID。这是本篇博文重点要记的,也是我所说的需要记忆的细节之处。下面就介绍一下ACID:

A、原子性(atomicity)

一个事务必须被视为一个不可分割的最小工作单位,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作。这也就解开了本篇博文开头的疑问。

C、一致性(consistency)

数据库总是从一个一致性的状态转换到另一个一致性的状态。在前面的例子中,即使在执行第三、四条语句之间时系统崩溃,支票账户中也不会损失200元,储蓄帐户也不会多出200元。因为事务最终没有提交,如果所有语句都顺利执行完成,并且事务也提交成功,那么就转换到了另一个一致性。尤其是在进行多表update的时候,根据业务的操作,在更新前是一个一致性状态,更新成功后又是另一个一致性状态(因为更新后的数据结果就是预期的结果)。

I、隔离性(isolation)

通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的,在前面的例子中,当执行完第三条语句,第四条语句还未开始时,此时有另外一个帐户汇总程序开始运行,则其看到的支票账户的额并没有减去200元。在下一篇博文中将理解讨论隔离级别(isolation level),那时你会发现为什么要说“同样来说”是不可见的。当然,关于隔离级别见这篇文章《Mysql事务以及隔离级别》。

D、持久性(durability)

一旦事务提交,则其所做的修改就会永久保存到数据库中。此时系统崩溃也不会影响到已经修改的数据了。话说持久性是个模糊的概念,因为实际上持久性也分很多不同的级别。有些持久性策略能够提供非常强的安全保障,而有些未必。而且不可能有能做到100%的持久性保证的策略(如果数据库本身就能做到真正的持久性,那么还需要备份来增加持久性做什么呢?).

虽然事务的ACID特性可以增加事务处理过程中额外的安全性,但如同锁粒度的升级会增加系统开销一样(详见上一篇博文《了解mysql的并发控制》),这也会需要数据库系统做更多的工作。因此一个实现了ACID的数据库,相比没有实现ACID的数据库,通常会需要更强的CPU处理能力、更大的内存和更多的磁盘空间。当然用户可以根据业务是否需要事务处理,来选择合适的存储引擎。对于一些非事务性的存储引擎,可以获得更高的性能。 本篇重点理解ACID的概念,如有疑问,欢迎留言探讨。