数据库事务和隔离级别的理解
数据库事务和隔离级别的理解
1.事务的概念
事务指逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功。
2. MySQL数据库事务操作命令
直接通过例子来说明
1.事务开始但没有提交
start transaction事务开始
mysql> start transaction;
Query OK, 0 rows affected
mysql> update product set price=price+100 where id=3;
Query OK, 1 row affected
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update product set price=price-100 where id=4;
Query OK, 1 row affected
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from product;
+----+----------+-------+-----+
| id | name | price | num |
+----+----------+-------+-----+
| 3 | nike | 988 | 2 |
| 4 | ads | 588 | 2 |
+----+----------+-------+-----+
当我直接关闭当前的dos窗口,没有提交事务的时候再次select会发现之前的操作没有成功。
mysql> select * from product;
+----+----------+-------+-----+
| id | name | price | num |
+----+----------+-------+-----+
| 3 | nike | 888 | 2 |
| 4 | ads | 688 | 2 |
+----+----------+-------+-----+
2.事务开始并提交
mysql> start transaction;
Query OK, 0 rows affected
mysql> update product set price=price+100 where id=3;
Query OK, 1 row affected
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update product set price=price-100 where id=4;
Query OK, 1 row affected
Rows matched: 1 Changed: 1 Warnings: 0
mysql> commit;
Query OK, 0 rows affected
mysql> select * from product;
+----+----------+-------+-----+
| id | name | price | num |
+----+----------+-------+-----+
| 3 | nike | 988 | 2 |
| 4 | ads | 588 | 2 |
+----+----------+-------+-----+
3.回滚操作rollback(在commit之前才有效)
mysql> start transaction;
Query OK, 0 rows affected
mysql> update product set price=price+100 where id=2;
Query OK, 1 row affected
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update product set price=price+100 where id=1;
Query OK, 1 row affected
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from product;
+----+----------+-------+-----+
| id | name | price | num |
+----+----------+-------+-----+
| 1 | 伊利 | 168 | 1 |
| 2 | 蒙牛 | 188 | 1 |
+----+----------+-------+-----+
mysql> rollback; 回滚
Query OK, 0 rows affected
mysql> select * from product;
+----+----------+-------+-----+
| id | name | price | num |
+----+----------+-------+-----+
| 1 | 伊利 | 68 | 1 |
| 2 | 蒙牛 | 88 | 1 |
+----+----------+-------+-----+
3.JDBC中使用事务
当Jdbc程序向数据库获得一个Connection对象时,默认情况下这个Connection对象会自动向数据库提交在它上面发送的SQL语句。若想关闭这种默认提交方式,让多条SQL在一个事务中执行,可使用下列的JDBC控制事务语句
- Connection.setAutoCommit(false);//开启事务(start transaction)
- Connection.rollback();//回滚事务(rollback)
- Connection.commit();//提交事务(commit)
具体有关JDBC连接数据库的操作可以看这篇文章:
4.事务的四大特性
1.原子性(Atomicity)
事务是一个不可分割的单位,事务中的操作要么全部成功,要么全部失败。
2.一致性(Consistency)
事务必须使数据库从一个一致性状态转变到另一个一致性状态;举个例子:A和B的总额为2000,无论他们之间如何转账,他们的总金额必须不变,这就是一致性。
3.隔离性(isolation)
多个用户并发访问数据库时,数据库为每个用户开启事务,不会被其他事务操作所影响,多个并发事务操作互相隔离。这个隔离性有四种级别。
4.持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响
5.并发事务可能出现的问题
5.1.脏读
事务A读取了事务B更新的数据,然后事务B回滚了,那么事务A读取的数据是脏数据,因为事务A读取了事务B未提交的数据。
5.2.不可重复读
事务A多次读取同一个数据,但是事务B在事务A的读取间隙更新并提交了数据,导致事务A读取结果不一致。
5.3.幻读
这里经常会和不可重复读弄混淆,首先明白一点幻读并不是说“一个事务内进行两次相同操作居然得到了不一样的结果” 直接从例子入手:
T1: select * from test where id=1;
T2: insert into test(id,name) values(1,“A”) ;
T1: insert into test(id,name) values(1,“A”) ;
T1:检索id=1的数据,发现没有,插入。
T2:干扰T1事务的进行,在T1事务插入数据之前,先插入数据提交。
T1:此时T1插入数据,会报主键冲突。
对于T1来说第一次的查询并不能支持插入操作,但实际上是可以的,T1这里就是发生了幻读,数据就像凭空出现的一样。
所以 mysql 的幻读并非什么读取两次返回结果集不同,而是事务在插入事先检测不存在的记录时,惊奇的发现这些数据已经存在了,之前的检测读获取到的数据如同鬼影一般。
这里要灵活的理解读取的意思,第一次select是读取,第二次的 insert 其实也属于隐式的读取,只不过是在 mysql 的机制中读取的,插入数据也是要先读取一下有没有主键冲突才能决定是否执行插入。
不可重复读侧重表达 读-读,幻读则是说 读-写,用写来证实读的是鬼影。
6.事务的隔离级别
6.1.读未提交(read uncommitted)
可以读取未提交的数据,会出现上面的脏读现象(此隔离级别不会使用,不做解释)
6.2.读已提交(read committed)
不能读取未提交的数据,这里就防止了脏读现象,但是避免不了不可重复读
时间 | 事务A | 事务B |
---|---|---|
T1 | 开始事务 | |
T2 | 开始事务 | |
T3 | 查询余额1000 | |
T4 | 查询余额100 | |
T5 | 取出1000,余额0 | |
T6 | 提交 | |
T7 | 查询余额0 | |
T8 | 提交 |
从上面我们可以看出事务A什么都没做 只是查询了两次数据,余额就从1000变成0
6.3.可重复读(repeatable-read)(MySQL/InnoDB下的默认级别)
针对当前读,RR隔离级别保证对读取到的记录加锁 (记录锁),同时保证对读取的范围加锁,新的满足查询条件的记录不能够插入 (间隙锁),不存在幻读现象。
6.4.串行化(serializable)
从MVCC并发控制退化为基于锁的并发控制。不区别快照读与当前读,所有的读操作均为当前读,读加读锁 (S锁),写加写锁 (X锁)。
Serializable隔离级别下,读写冲突,因此并发度急剧下降,在MySQL/InnoDB下不建议使用。
有关mysql加锁情况这篇文章有详细的解释:https://blog.csdn.net/qq_38238296/article/details/88362999