事务的属性ACID
A 原子性 Redo & Undo
C 一致性 Undo
I 隔离性 Lock
D 持久性 Redo
Atomic(原子性)
所有语句作为一个单元全部成功执行或全部取消
AUTOCOMMIT, COMMIT, ROLLBACK
Consistent(一致性))
如果数据库在事务开始时处于一致状态,则在执行该事务期间将保留一致状态
Innodb doublewrite buffer, crash recovery
Isolated(隔离性)
事务之间不相互影响
SET ISOLATION LEVEL
Durable(持久性)
事务成功完成后,所做的所有更改都会准确地记录在数据库中
所做的更改不会丢失
Innodb doublewrite buffer, redo log, sync_binlog
并发存在的问题
脏读
不可重复读
幻读
事务的隔离级别
Read Uncommitted 读未提交
Read Commited 读已提交
Repeatable Read 可重复读
Serializable 串行
脏读
会话一 查询 id=1 name=a
会话二 update -> a 改成b
会话一 再查询的时候 name 值变成了b
不可重复读
会话一 查询 name值为 A
会话二 update A 值改成 B值
会话一 查询name 值 变成 B了
幻读
第一次查询 id = 1 name 等于 A
第二次查询 id = 1 name 等于 A,B 多出来了一条记录
CREATE TABLE `t1` (
`id` int(11) NOT NULL DEFAULT '0',
`name` varchar(10) DEFAULT NULL,
PRIMARY KEY (`id`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into t1 values(1,'AAAA');
insert into t1 values(2,'BBBB');
脏读测试
show variables like '%iso%';
READ-COMMITTED
#set tx_isolation='READ-UNCOMMITTED' #5.6版
set transaction_isolation='READ-UNCOMMITTED';
两个会话同时设置成 RU
会话一开始事务,修改数据但未提交事务 begin; update t1 set name='AAAAAA' where id=1;
会话二查询的时候 发现数据已经变更了
rollback;
不可重复读
会话一 select * from t1 where id=1; name = aaaa
会话二 update t1 set name='AAAAA' where id=1; commit;
会话一 select * from t1 where id=1; 发现name = AAAAA 了
幻读
会话一
begin;
select * from t1 where id >= 1;
会话二 insert into t1 values(3,'CCCCC');commit;
会话一 select * from t1 where id >= 1; 发现多了一条数据
Oracle 默认的隔离级别是 RC MSSQL DBS PostgreSQL
MySQL 默认的隔离级别是 RR
隔离级别改为RR
set transaction_isolation='REPEATABLE-READ';
show variables like '%iso%';
重复读案例
CREATE TABLE t1
(
id
int(11) NOT NULL DEFAULT '0',
name
varchar(10) DEFAULT NULL,
PRIMARY KEY (id
)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into t1 values(1,'aaaaa');
insert into t1 values(2,'bbbbb');
会话一
begin;
select * from t1 where id=1; //name = aaaaa
会话二
begin;
update update t1 set name='AAAAA' where id=1; //修改值并提交
commit;
会话一:
select * from t1 where id=1; //查询到的值 还是 aaaaa
网友评论