ACID
当我们学习数据库事务的时候,我们就知道了事务有4个特性,分别是原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
原子性
要么全部成功,要么全部失败,只要有一个失败,已经成功的都要回滚。
比如A账号给B账号转账100块钱,正常情况是A扣款100块,然后B账号增加100块。如果A这边扣款成功,B增加100块的时候失败了,这个时候,A扣款的操作就要回滚,也就是A也不扣款,B也没新增。
一致性
wikipedia包含这类描述
Any data written to the database must be valid according to all defined rules, including constraints, cascades, triggers, and any combination thereof.
数据的写入,必须符合我们的定义的规则。比如我们定义了金额是数值型,那么久不能传入字符串。我们定义了金额不能小于0,那就不能赋值为负数(这个是我们程序定义的)。
隔离性
指并发中的事务,即便操作共同的数据时,每个是事务是相互隔离的,相互不能影响的,每个事务都有自己完整的事务空间。
隔离级别从低到高:
Read Uncommitted(读未提交):
- 事务1更新id为1的name为张三
- 事务2读取id为1的name,此时读取的值为张三
- 事务1更新id为1的name为李四
- 事务2读取id为1的name,此时读取的值为李四
在事务1还没提交的时候,事务2可以读取到事务1更改的值。
Read Committed(读已提交):
- 事务2读取id为1的name,假设读取的初始值为李四
- 事务1更新id为1的name为张三
- 事务2读取id为1的name,读取值为李四(这个跟上面不一样,此时事务1还没提交,是看不到修改后的值)
- 事务1提交
- 事务2读取id为1的name,此时读取的值为张三
上面例子可以看出,在同一个事务中,事务2读取的值是不一样的。
Repeated Read(重复读):
图跟上面一样
- 事务2读取id为1的name,假设读取的初始值为李四
- 事务1更新id为1的name为张三
- 事务2读取id为1的name,读取值为李四(这个跟上面不一样,此时事务1还没提交,是看不到修改后的值)
- 事务1提交
- 事务2读取id为1的name,此时读取的值为李四(这个与上面不一样的地方)
Serialization(串行化):
- 事务2读取id为1的name,假设读取的初始值为李四
- 事务1更新id为1的name为张三,被阻塞了,等user表的id为1的事务提交,这个时候,id为1的这行被锁住了。
- 事务2执行范围的查询语句
- 事务1修改或插入数据,都被阻塞,这个时候,user表都锁住了。
串行化,就是所有的事务串行的执行,一个事务执行才,才能执行后面一个。
读现象
脏读
当一个事务读取到另一个事务未提交的数据,就可能发生脏读。
参见读未提交的例子。
不可重复读
在一次事务中,查询多次的结果不是一致的,这表明发生不可重复读。
参见读已提交的例子。
幻影读
在一次事务中,查询多次的结果集不是一致的。
- 事务2查询id在1到10直接的名称,假设有5个
- 事务1插入id为9的数据
- 事务1提交
- 事务2查询id在1到10直接的名称,此时有6个
隔离级别和读现象的关系
持久性
指事务一旦提交,就永久保留下来。系统崩溃、机器宕机,只要重启数据库,就可以读取到数据。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。