本部分主要介绍:事务的 4 种隔离级别,及对应解决 3 种数据问题,和如何修改数据库的默认事务隔离级别
事务隔离性(Isolation)解释
数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。并发执行的事务之间不能相互干扰
事务隔离分为不同级别
-
读未提交(Read uncommitted):允许事务读取未被其他事务提交的变更。脏读、不可重复、幻读问题都会出现
- 例如,事务1,可以读取到事务2 已经修改,但是还没有提交的数据
-
读提交(read committed):只允许事务读取已被其他事务提交的变更。可以避免脏读,但不可重复和幻读问题依然会出现
- 例如,事务1,只可以读取事务2 已提交的数据
可重复读(repeatable read):确保事务可以多次从一个字段读取相同的值,这个事务在持续期间,禁止其他事务对该字段进行更新。可以避免脏读和不可重复读,但幻读问题仍然存在(随着 mysql 的优化,次级别也可以避免幻读)。
串行化(Serializable):确保事务可以从一个表中读取相同行。这个事务在持续期间,禁止其他事务对该表进行更新、插入、删除。可以避免脏读、不可重复读和幻读问题,但性能超低。
脏读、不可重复读、幻读现象
脏读现象(针对未提交的记录):事务1 对表的某个记录进行修改,但还未提交,事务2 就可以查看事务1 未提交的数据。这样造成的问题是,如果事务1 回滚,那么事务2 在此之前所查看的数据就是脏数据。
不可重复的现象(针对表中行的数据):是指同一个事务在整个事务过程中对表中同一记录进行读取,每次读取结果都不同。事务1 对表的某个记录进行修改,并已提交。在事务1 提交之前,事务2 查询了该条记录;在提交之后,事务2 又查询该条记录。
幻读现象(针对记录的条数):是指同一个事务在整个事务过程中对表中的记录进行读取,查询所得的结果集是不一样的(行数不同)。在事务1 提交之前,事务2 查询了表中记录;在提交之后,事务2 又查询表中记录。两次读取的表中记录数不同
-
不可重复与幻读的区别
- 不可重复针对的是表中的记录的数据不同;幻读是针对查询的结果集数量不同(记录条数不同)
事务隔离级别的作用
-
事务不同放入隔离级别可以分别解决数据的脏读、不可重复和幻读问题
-
如表(1 表示可能出现,0 表示可以避免)
事务级别 脏读 不可重复读 幻读 read uncommitted(读未提交) 1 1 1 read committed(读提交) 0 1 1 repeatable read(可重复读) 0 0 1(mysql 优化后也可以避免) serializable(串行化) 0 0 0
-
-
对事物级别和问题的理解
读未提交、读提交 是针对提交而言
可重复读 是针对记录(行)而言,事务持续期间将操作的表中记录(行)锁住禁止更新(优化后幻读也可以解决)。
幻读 是将操作的表锁住,禁止更新、插入、删除。
设置 mysql 的事务隔离级别
-
查看 mysql 默认隔离级别
查看当前的隔离级别
select @@tx_isolation;
-
查看全局隔离级别
select @@global.tx_isolation;
mysql> select @@tx_isolation; +-----------------+ | @@tx_isolation | +-----------------+ | REPEATABLE-READ | +-----------------+ 1 row in set, 1 warning (0.00 sec)
-
修改事务隔离级别
修改全局 (永久有效)
set global tx_isolation = 'read-committed';
只对本次连接有效
set tx_isolation = 'read-uncommitted';