什么是事务
事务是一组操作,组成这组操作的各个单元,要不全都成功要不全都失败,这个特性就是事务。
事务的四大特性ACID
原子性(Atomicity)
原子性指的就是 MySQL 中的包含事务的操作要么全部成功、要么全部失败回滚,因此事务的操作如果成功就必须要全部应用到数据库,如果操作失败则不能对数据库有任何影响。
一致性(Consistency)
一致性指的是一个事务在执行前后其状态一致。比如A和B加起来的钱一共是 1000 元,那么不管A和B之间如何转账,转多少次,事务结束后两个用户的钱加起来还得是 1000,这就是事务的一致性。
持久性(Durability)
持久性指的是一旦事务提交,那么发生的改变就是永久性的,即使数据库遇到特殊情况比如故障的时候也不会产生干扰。
隔离性(Isolation)
当多个事务同时进行时,就有可能出现脏读(dirty read)、不可重复读(non-repeatable read)、幻读(phantom read) 的情况,为了解决这些并发问题,提出了隔离性的概念。
脏读
事务T1读取了事务T2更新后的数据,但是事务T2没有提交,然后事务T2执行回滚操作,那么事务T1读到的数据就是脏数据。
不可重复读
事务T1进行多次读取操作,事务T2在事务T1多次读取的过程中执行更新操作并提交,提交后事务T1读到的数据不一致。
幻读
事务T1将数据库中所有学生的成绩由A->B,此时事务T2手动插入了一条成绩为A的记录,在事务T1更改完毕后,发现还有一条记录没有修改,那么这种情况就叫做出现了幻读。
4种隔离级别
未提交读(read uncommited):
未提交读指的是一个事务在提交之前,它所做的修改就能够被其他事务所看到。允许脏读。
提交读(read commited):
已提交读指的是一个事务在提交之后,它所做的变更才能够让其他事务看到。oracle等数据库默认都是改级别(不重复读)。
可重复读(repeatable read):
可重复读指的是一个事务在执行的过程中,看到的数据是和启动时看到的数据是一致的。未提交的变更对其他事务不可见。InnoDB默认级别,在SQL标准中,该级别消除了不可重复读,但是还存在幻读的可能。
串行读(serializable):
顾名思义是对于同一行记录,写会加写锁,读会加读锁。读写相互阻塞,当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。
事务级别查询和设置
设置事务级别
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
查询事务级别
SELECT @@global.tx_isolation;
SELECT @@session.tx_isolation;
SELECT @@tx_isolation;
举例
脏读例子:
session1:
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
mysql> insert into user(name) value('p');
Query OK, 1 row affected (0.00 sec)
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into user(name) value('iu');
Query OK, 1 row affected (0.00 sec)
session2:
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
mysql> select * from user;
+----+------+
| id | name |
+----+------+
| 1 | p |
+----+------+
1 row in set (0.00 sec)
session3:(出现了脏读)
mysql> set session transaction isolation level read uncommitted;
Query OK, 0 rows affected (0.00 sec)
mysql> select @@tx_isolation;
+------------------+
| @@tx_isolation |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set (0.00 sec)
mysql> select * from user;
+----+------+
| id | name |
+----+------+
| 1 | p |
| 2 | iu |
+----+------+
2 rows in set (0.00 sec)
总结
隔离级别由低到高是:未提交读 < 已提交读 < 可重复读 < 串行化
隔离级别越高,越能够保证数据的完整性和一致性,但是对并发的性能影响越大。大多数数据库的默认级别是读已提交(Read committed),比如 Sql Server、Oracle ,但是 MySQL 的默认隔离级别是 可重复读(repeatable-read)