阅读(1832) (1)

HasorDB 隔离级别

2021-12-28 15:12:58 更新

下面不同的隔离级别均已下面这张表为例子:

mysql> select * from students;
+----+-------+
| id | name |
+----+-------+
| 1 | Alice |
+----+-------+
1 row in set (0.00 sec)

DEFAULT​

  • HasorDB 常量 ​Isolation.DEFAULT
  • JDBC 常数​ Connection.TRANSACTION_NONE

默认事务隔离级别,具体使用的数据库事务隔离级别由底层决定。

提示
相当于没有设置,但具体行为由驱动决定。

未提交读取(Read Uncommitted,也称为脏读)​

  • HasorDB 常量​ Isolation.READ_UNCOMMITTED
  • JDBC 常数 ​Connection.TRANSACTION_READ_UNCOMMITTED

Read Uncommitted 是隔离级别最低的一种事务级别。在这种隔离级别下,一个事务会读到另一个事务更新后但未提交的数据,如果另一个事务回滚,那么当前事务读到的数据就是脏数据。

时间 事务1 事务2 效果
T1 set transaction isolation level read uncommitted;
T2 begin; begin;
T3 update students set name = 'bob' where id = 1;
T4 select * from students where id = 1; 可以看到 事务1 变更后的数据
T5 rollback;
T6 select * from students where id = 1; 可以看到 事务1 回滚后的数据
T7 commit;

不可重复读 (Read Committed)​

  • HasorDB 常量 ​Isolation.READ_COMMITTED
  • JDBC 常数 ​Connection#TRANSACTION_READ_COMMITTED

Read Committed 不可重复读,是指在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据。

时间 事务1 事务2 效果
T1 set transaction isolation level read committed; set transaction isolation level read committed;
T2 begin; begin;
T3 select * from students where id = 1; 原始数据
T4 update students set name = 'bob' where id = 1;
T5 select * from students where id = 1; 此时 事务2 看到的仍然是 原始数据
T6 commit;
T7 select * from students where id = 1; 此时 事务2 再次查询看到的数据和 原始数据 不一样
T8 commit;

可重复读取 (Repeatable Read)​

  • HasorDB 常量 ​Isolation.REPEATABLE_READ
  • JDBC 常数 ​Connection#TRANSACTION_REPEATABLE_READ

可重复读(Repeatable Read),当使用可重复读隔离级别时,在事务执行期间会锁定该事务以任何方式引用的所有行。

在 Repeatable Read 隔离级别下,一个事务可能会遇到幻读(Phantom Read)的问题。 幻读是指,在一个事务中,第一次查询某条记录,发现没有。但是,当试图更新这条不存在的记录时,竟然能成功。并且,再次读取同一条记录,它就神奇地出现了。

时间 事务1 事务2 效果
T1 set transaction isolation level repeatable read; set transaction isolation level repeatable read;
T2 begin; begin;
T3 select * from students where id = 99; 不存在的数据
T4 insert into students (id, name) values (99, 'bob');
T5 commit;
T6 update students set name = 'alice' where id = 99; 可以成功更新
T7 select * from students where id = 99;
T8 commit;
  • 在 T6 环节,由于 事务1 已经在 T5 环节递交。因此更新可以被成功执行,但是相对于 T3 环节成功更新了一个不存在的数据。这就是 幻读

同步事务 (Serializable)​

  • HasorDB 常量 ​Isolation.SERIALIZABLE
  • JDBC 常数​ Connection#TRANSACTION_SERIALIZABLE

提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,不能并发执行。因此,脏读、不可重复读、幻读都不会出现。

Serializable​ 隔离级别相当于在开启事务的时候,对整个数据库加了 排他锁,直到第一个事务被 commit 否则其它事务无法开始。 因此效率会大大下降,一般没有没有特别重要的情景,都不会使用 ​Serializable ​隔离级别。