数据库之事务
程序员文章站
2024-01-14 09:51:16
...
定义
事务是一组原子性的SQL查询,或者说一个独立的工作单元。如果数据库引擎能够成功地对数据库应用该组查询的全部语句,那么就执行该组查询。如果其中一条语句因为崩溃或其他原因无法执行,那么多有的语句都不会执行。也就是说,事务内的语句,要么全部执行成功,要么全部执行失败。
通俗的讲,事务就是一件事情。是一个不可分割的整体,就像化学原子一样,是构成物质的最小单元。
ACID
原子性(Atomicity):一个事务被视为一个不可分割的最小工作单元,整个事务内的所有操作,要么全部执行,要么全部失败回滚,不可能只执行其中的一部分。
一致性(Consistency):即执行完数据库操作后,数据不会被破坏。比如A账户转账给B账户,不能因为A账户扣了钱,而B账户没有扣钱。
隔离性(Isolation):通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的。这里需要注意隔离级别,之后会详细讲。
持久性(Durability):一旦事务提交,则其所做的修改就会永久保存到数据库中。
隔离级别
READ_UNCOMMITTED(未提交读)
READ_COMMITTED(提交读)
REPEATABLE_READ(可重复读)
SERIALIZABLE(可串行化)
从上往下,级别越来越高,并发性能越来越差,安全性越来越高。
之所以定义这几种级别,主要是为了解决数据在高并发行下产生的问题:
脏读(Dirty Read)
不可重复读(Unrepeatable Read)
幻读(Phantom Read)
脏读
并发执行的两个事务
余额应该为1500元才对。在T5时间点,事务A此时查询余额为0元,这个数据就是脏数据,它是事务B造成的,明显事务没有隔离,乱套了。
所以脏读这件事情造成的后果非常严重,一定要解决。必须让事务隔离起来。
不可重复读
不可重复读示例
事务A其实除了查询了两次以外,其他什么事情都没有做,结果钱及从1000变成0了,这就是重复读。其实这样也是合理的,毕竟实务B提交了事务,将数据库结果进行了持久化,所以事务A再次读取时就自然发生了变化。
这种现象基本是可以理解的,但有些特殊场景下却是不允许的。毕竟这种现象也是事务之间没有隔离所造成的。
幻读
幻读示例
事务A在T3时刻和T6时刻统计的总存款数不同,这就是幻读。虽然看起来正常,但在一些要求严格的系统中,比如银行,这是不允许的。
总结
脏读:事务A读取了事务B未提交的数据,并在这个基础上又做了其它操作。
不可重复读:事务A读取了事务B已提交的更改数据。
幻读:事务A读取了事务B已提交的新增数据。
事务隔离级别