什么是事务
事务是数据库管理系统(DBMS)执行过程中的一个逻辑单位(不可再进行分割),由一个有限的数据库操作序列构成(多个DML语句,select语句不包含事务),要不全部成功,要不全部不成功。
如 A 给 B 要划钱,A 的账户-1000 元, B 的账户就要+1000 元,这两个 update 语句必须作为一个整体来执行,不然 A 扣钱了,B 没有加钱这种情况就是错误的。那么事务就可以保证 A 、B 账户的变动要么全部一起发生,要么全部一起不发生。
事务特性
事务具有 4 个属性:原子性(atomicity)、一致性(consistency)、隔离性(isolation)、持久性(durability)。这四个属性通常称为 ACID 特性。
原子性
一个事务必须被视为一个不可分割的最小单元,整个事务中的所有操作要么全部提交成功,要么全部失败,对于一个事务来说,不能只执行其中的一部分操作。
比如: A 给 B 转钱,A 扣除 500 元 ,B 增加 500 元
整个事务的操作要么全部成功,要么全部失败,不能出现 A 扣钱,但是 B 不增加的情况。如果原子性不能保证,就会很自然的出现一致性问题。
一致性
一致性是指事务将数据库从一种一致性转换到另外一种一致性状态,在事务开始之前和事务结束之后数据库中数据的完整性没有被破坏。
即 A 给 B 转钱,A 扣除 500 元 ,B 增加 500 元,扣除的钱(-500) 与增加的钱(+500) 相加应该为 0。
隔离性
一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
如果隔离性不能保证,会导致什么问题?
假如 A 开始有 1000,B 没有钱,然后 A 给 B 转了 2 次钱,第一次转 500,第二次也转 500,如果我们把这两次转钱操作分别称为 T1 和 T2,则在正常情况下,应该是一次一次的来进行转账,但在数据库中可能出现交替的情况,如:
T1 | T2 |
---|---|
读:A = 1000 | |
读:A = 1000 | |
A - 500 = 500 | |
B + 500 = 500 | |
读:B = 500 | |
A - 500 = 500 | |
B + 500 = 1000 |
按照上面的方式 A 此时还剩余 500,而 B 已经为 1000,相当于多了 500。
持久性
一旦事务提交,则其所做的修改就会永久保存到数据库中。此时即使系统崩溃,已经提交的修改数据也不会丢失。
事务并发
我们知道 MySQL 是一个客户端/服务器架构的软件,对于同一个服务器来说,可以有若干个客户端与之连接,每个客户端与服务器连接上之后,就可以称 之为一个会话(Session)。每个客户端都可以在自己的会话中向服务器发出请求 语句,一个请求语句可能是某个事务的一部分,也就是对于服务器来说可能同时处理多个事务。
在上面我们说过事务有一个称之为隔离性的特性,理论上在某个事务对某个数据进行访问时,其他事务应该进行排队,当该事务提交之后,其他事务才可以继续访问这个数据,这样的话并发事务的执行就变成了串行化执行。
但是对串行化执行性能影响太大,我们既想保持事务的一定的隔离性,又想让服务器在处理访问同一数据的多个事务时性能尽量高些,当我们舍弃隔离性的时候,可能会带来什么样的数据问题呢?
隔离级别
MySQL 具有四种事务隔离级别,隔离力度依次递增,高度隔离会限制可并行执行的事务数,所以一些应用程序降低隔离级别以换取更大