数据库事务ACID

数据库事务的几个特性:
原子性(Atomicity),一致性(Consistency),隔离性或独立性(Isolation)和持久性(Durabilily),简称就是ACID

原子性

事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。

一致性

事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
举例:在转账之前,A和B的账户中共有500+500=1000元钱。在转账之后,A和B的账户中共有400+600=1000元。

隔离性

多个事务并发执行时,一个事务的执行不应影响其他事务的执行。

持久性

一个事务一旦提交,他对数据库的修改应该永久保存在数据库中。

隔离性的相关问题

  1. 脏读(Dirty Read)
    脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据。

  2. 不可重复读(Nonrepeatable Read)
    不可重复读是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。

  3. 幻像读(Phantom Reads)
    是事务非独立执行时发生的一种现象。例如事务T1对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作,这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务T1的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务T2中添加的。

  4. 丢失修改(Lost Update)
    第一类:当两个事务更新相同的数据源,如果第一个事务被提交,第二个却被撤销,那么连同第一个事务做的更新也被撤销。
    第二类:有两个并发事务同时读取同一行数据,然后其中一个对它进行修改提交,而另一个也进行了修改提交。这就会造成第一次写操作失效。

为了兼顾并发效率和异常控制,在标准SQL规范中,定义了4个事务隔离级别:

  1. Serializable (序列化):
    意思是说这个事务执行的时候不允许别的事务并发执行。完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞。
    Serializable 不允许不一致现象的出现。可避免脏读、不可重复读、幻读的发生。

  2. Repeatable read (可重复读):
    在同一个事务里面先后执行同一个查询语句的时候,得到的结果是一样的。
    Repeatable Read 可避免脏读、不可重复读的发生,但是会出现幻象读。

  3. Read committed (已提交读):
    语句提交以后,即执行了 Commit 以后别的事务就能读到这个改变,只能读取到已经提交的数据。
    Read Commited 可避免脏读的发生,但会出现非重复读。

  4. Read uncommitted (未提交读):
    意思就是即使一个更新语句没有提交,但是别的事务可以读到这个改变。
    最低级别,任何情况都无法保证。

以上四种隔离级别最高的是Serializable级别,最低的是Read uncommitted级别,当然级别越高,执行效率就越低。

事务隔离的实现——锁

  1. 共享锁(S锁)
    用于只读操作(SELECT),锁定共享的资源。共享锁不会阻止其他用户读,但是阻止其他的用户写和修改。

  2. 更新锁(U锁)
    用于可更新的资源中。防止当多个会话在读取、锁定以及随后可能进行的资源更新时发生常见形式的死锁。

  3. 独占锁(X锁,也叫排他锁)
    一次只能有一个独占锁用在一个资源上,并且阻止其他所有的锁包括共享缩。写是独占锁,可以有效的防止“脏读”。