事务定义了一个服务操作序列,由服务器保证这些操作序列在多个客户并发访问和服务器出现故障情况下的原子性。
事务是在数据库管理系统领域发展起来的,是一种对共享数据库进行并发访问或错误处理的泛型。
在数据库中操作DML(insert,update,delete,select)或DDL(创建,改变表结构)都会发生事务。
事务的4个属性:ACID:原子性、一致性、隔离性、持久性。
解决原子性的技术:Redo & Undo;
解决一致性的技术:Undo;
解决隔离性的技术:Lock;
解决持久性的技术:Redo;
下面还要介绍下事务的隔离级别:
Read Uncommitted:读未提交
Read Commited:读已提交
Repeatable Read:可重复读
Serializable:串行
Read Uncommitted 级别很低,但并发很高。
oracle用Read Commited,这个级别
mysql默认级别为Repeatable read
serializable就相当于只有一个人用。
这张图说明了各个级别存在及解决的问题:
mysql当隔离级别为Repeatable Read的时候,可以解决幻读。
但这也有个问题,并发从上到下,依次减少。
下面来演示下并发会存在的三个问题:
脏读(dirty read)、不可重复读(unrepeatable read)、幻读(phantom read)。
脏读就是读了脏数据。
下面演示下什么叫脏读:
上面的表中是隔离级别解决的问题。现在查下目前mysql的隔离级别:
show variables like '%iso%';
可见这种默认级别是演示不了脏读的。得进行修改,改为:READ-UNCOMMITTED
set tx_isolation='READ-UNCOMMITTED';
演示以这种表为例:
show tables;
select * from test;
desc test;
在session1中,更新一条数据,然后未提交:
begin;
update test set name='DDDDD' where id = 1;
在session2上进行查询,就是被修改后的数据,这就是脏数据:
show variables like '%iso%';
set tx_isolation='READ-UNCOMMITTED';
select * from test;
这里可以看到,读了未提交的数据,就是脏读。
下面session1进行回滚:
session2又正常了:
select * from test;
下面演示下不可重复读的问题:
在session1中查询单条数据:
select * from test where id = 1;
在会话2中对这个数据进行修改:
在session1中再次进行select:
select * from test where id = 1;
这种session1中存在的问题,就是不可重复读。
下面演示下幻读
在session1中查询:
select * from test where id > 1;
在session2中插入一条数据:
begin;
insert into test values(4, 'EEEEEEEEEEEE');
在session1中再查:
select * from test where id > 1;
多出来了一条,这就是幻读