目录
数据库三范式
1、表的列具有原子性 不可拆分性
2、表的列只有唯一依赖
3、表的列不能有传递依赖
脏读、不可重复读、幻读
背景:
insert into test values(null, 1, 'yh');
--默认自动提交
-
脏读
在A事务中读取了B事务未提交的数据,若B事务回滚后,A就是脏读。 重点:读一次
现象:
B事务:
set autocommit = 0;
start TRANSACTION;
update test set age = 10 where id = 1;
-- 等待A事务查询
rollback;
A事务:(另一个查询窗口)
set session TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
select * from test; -- 结果age=10
这里A读取的数据就是脏数据。
解决:读取时设置事务隔离级别为 READ COMMITED
事务A
set session TRANSACTION ISOLATION LEVEL READ COMMITTED;
-
不可重复读
在A事务中两次读取数据不一致,就是不可重复读。 重点:读两次
现象:
A事务:
set session TRANSACTION ISOLATION LEVEL READ COMMITTED; -- read uncommited结果一样
start TRANSACTION;
select * from test; -- 查询结果age=1
//等待 B事务处理完
select * from test; --再次查询 age=10
commit;
B事务:(另一个查询窗口)
set autocommit = 0;
start TRANSACTION;
update test set age = 10 where id = 1;
commit;
解决:读取时将隔离级别设置为 REAPTABLE READ
事务A中
set session TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-
幻读
一个事务中读取的结果集条数不一样,增加或减少了记录。 重点:结果集数据
现象:
A事务:
set session TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- READ UNCOMMITED, READ COMMITTED 结果也是一样的
start TRANSACTION;
select * from test; -- 查询结果1条name=yh
//等待 B事务处理完
select * from test; --再次查询有2条数据 1条name=yh 1条name=double
commit;
B事务:(另一个查询窗口)
set autocommit = 0;
start TRANSACTION;
-- update test set age = 10 where id = 1;
-- 注意这里不是更新了,是新插入数据
insert into test values(null, 1, 'double');
commit;
解决:读取时将隔离级别设置为 SERIALIZABLE
事务A中
set session TRANSACTION ISOLATION LEVEL SERIALIZABLE;
总结:
脏读 | 不可重复读 | 幻读 | |
READ UNCOMMITTED | 会出现 | 会出现 | 会出现 |
READ COMMITTED | 会出现 | 会出现 | |
REPEATABLE READ | 会出现 | ||
SERIALIZABLE |
隔离级别等级比较:
READ UNCOMMITTED < READ COMMITTED < REPEATABLE READ < SERIALIZABLE
设置这个隔离级别跟写没什么关系,只跟读取方设置的隔离级别有关系。