MySQL事务隔离级别

事务的特性

  • 原子性:指处于同一个事务中的多条语句是不可分割的。
  • 一致性:事务必须使数据库从一个一致性状态变换到另外一个一致性状态。比如:转账—转账前两个账户余额之和为233¥,转账之后也应该是233¥。
  • 隔离性:指多线程环境下,一个线程中的事务不能被其他线程中的事务打扰
  • 持久性:事务一旦提交,就应该被永久保存起来。

事务的隔离性:隔离级别分类

如果不考虑事务的隔离性,则可能会出现以下问题:

  • 脏读:指一个线程中的事务读取到了另外一个线程中未提交的数据。
  • 不可重复读:指一个线程中的事务读取到了另外一个线程中提交的update的数据。
  • 虚读:指一个线程中的事务读取到了另外一个线程中提交的insert的数据。

隔离级别

  • 1-READ UNCOMMITTED: 脏读、不可重复读、虚读都有可能发生。
  • 2-READ COMMITTED: 防止脏读的发生,不可重复读、虚读都有可能发生。
  • 4-REPEATABLE READ: 防止脏读、不可重复读的发生,虚读有可能发生。
  • 8-SERIALIZABLE: 防止脏读、不可重复读、虚读的发生。

级别越高,数据越安全,相对就导致性能越低。


拿 MySQL 现身说法

查看当前事务的隔离级别:SELECT @@tx_isolation;

注意:更改事务的隔离级别,一定要在开启事务之前设置。

更改事务:SET transaction isolation level 四个级别之一(单词);

通过一个情景模拟来理解隔离级别:

-- 准备工作
create table t_account(
id int(11) primary key,
name varchar(30),
money float
);
insert into t_account(id,name,money) values
(1,'a',1000),
(2,'b',1000);
set transcation isolation level read uncommited;
-- 可打开两个 CMD 窗口连接 MySQL 来模拟两位用户~

时间点 线程1-自己 线程2-其他人 说明
t1 start transacion;
t2 select * from t_account
where name=’a’
a查询账户:我有1000元
t3 start transaction;
t4 update t_account set money=money+100
where name=’a’;
其他人:给a存100,逗逗他
t5 select * from t_account
where name=’a’
a再次查询账户,1100元(我靠,多了100块)!
读取到了另外一个
线程中未提交的数据,出现脏读
t6 commit;
t7 select * from t_account
where name=’a’
a又查询账户,发现还是1100元(踩到狗屎啦?)。
前后读到的数据不一致,
读到了另外一个线程中提交的 update 数据,
出现可重复读
t8 insert into t_account
values(2,’蛤蛤蛤’,233);
t9 select * from t_account; 还是让工作人员来确认下吧。
一查总用户,我凑又多了一个人叫“蛤蛤蛤”!
读到了另外一个线程中提交的 insert 数据,出现虚读
t10 commit; 工作人员提交事务,两人一脸懵逼……

JDBC 中控制事务的隔离级别:

前提:在开启事务之前设置隔离级别。

通过Connection中的整型常量代表不同的级别:

实际就是一个整数常量

设置事务的隔离级别:Connection:void setTransactionIsolation(int level);

手滑了就鼓励一下吧~