INFORMIX数据库隔离级别
多个事务对相同记录的并行访问,数据库提供隔离级别来控制数据的并发访问。隔离级别指定在执行并发 SQL 事务期间会出现的现象。可能会出现以下现象:
l 脏读。SQL 事务 T1 修改一行。然后 SQL 事务 T2 在 T1 执行 COMMIT 之前读取该行。如果 T1 接着执行 ROLLBACK,则 T2 将已经读取一个从未提交的行,因而也可以认为是一个从未存在过的行。
l 不可重复读取。SQL 事务 T1 读取一行。然后 SQL 事务 T2 修改或删除该行并执行 COMMIT。如果 T1 接着尝试重新读取该行,T1 可能会收到修改后的值或发现该行已被删除。
l 幻像行。SQL 事务 T1 读取满足某些搜索条件的多行的集合 N。然后 SQL 事务 T2 执行生成满足 SQL 事务 T1 所使用的搜索条件的一个或多个新行的 SQL 语句。如果 T1 接着使用相同的搜索条件重复原先的读取,则 T1 收到一个不同的多行的集合。
脏读,
下面通过示例说明dirty read(DR)--脏读 和 commited read (CR)—提交读两种数据库并行访问策略。
设置隔离级别方法:
DR:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
或者
Set isolation to dirty read;
CR:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
或者
Set isolation to commited read;
测试示例:
Create table test(t1 integer);
三个事务T1、T2、T3对表test1进行并发访问。
场景一:
T1: 对表test进行DML操作,更新表中记录。注意sleep(30)
begin work;
delete from test where 1=1;
sleep (30);
insert into test(t1) values(1);
insert into test(t1) values(2);
commit work;
T2:对表test设置提交读(CR),在T1运行第一SQL语句后启动并发运行。设置锁等待为60 seconds
begin work;
set lock mode to wait 60;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
select * from test where 1=1;
sleep(13);
select * from test where 1=1;
commit work;
T3:对表test设置脏读(DR),在T1运行第一SQL语句后启动并发运行
begin work;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
select * from test where 1=1;
sleep(35);
select * from test where 1=1;
commit work;
输出:
事务 | 输出1 | 输出2 |
T2 | 等待T1 COMMIT后输出: 1 2 | 等待T1 COMMIT后输出: 1 2 |
T3 | 不等待T1 结束,立即输出: No rows | 不等待T1 结束,sleep 35秒后输出: 1 2 |
场景二:
T1: 对表test进行DML操作,更新表中记录。注意sleep(30)
begin work;
delete from test where 1=1;
sleep (70);
insert into test(t1) values(1);
insert into test(t1) values(2);
commit work;
T2:对表test设置提交读(CR),在T1运行第一SQL语句后启动并发运行。设置锁等待为60 seconds
begin work;
set lock mode to wait 60;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
select * from test where 1=1;
sleep(13);
select * from test where 1=1;
commit work;
T3:对表test设置脏读(DR),在T1运行第一SQL语句后启动并发运行
begin work;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
select * from test where 1=1;
sleep(35);
select * from test where 1=1;
commit work;
输出:
事务 | 输出1 | 输出2 |
T2 | 由于设置的锁等待时长为60秒,而T1对表TEST的访问时长超过60秒,数据库返回: -154: ISAM error: Lock Timeout Expired 事务退出 | 由于设置的锁等待时长为60秒,而T1对表TEST的访问时长超过60秒,数据库返回: -154: ISAM error: Lock Timeout Expired 事务退出 |
T3 | 不等待T1 结束,立即输出: No rows | 不等待T1 结束,立即输出: No rows |
场景三:
T1: 对表test进行DML操作,更新表中记录。T2.T3启动后运行
begin work;
delete from test where 1=1;
sleep (10);
insert into test(t1) values(1);
insert into test(t1) values(2);
commit work;
T2:对表test设置提交读(CR)
begin work;
set lock mode to wait 60;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
select * from test where 1=1;
sleep(60);
select * from test where 1=1;
commit work;
T3:对表test设置脏读(DR)
begin work;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
select * from test where 1=1;
sleep(35);
select * from test where 1=1;
commit work;
输出:
事务 | 输出1 | 输出2 |
T1 | 等待T2结束后才能执行完成后续语句 |
|
T2 T2对TEST进行锁定,事务提交后,其他事务才可以对表进行DML操作 | 1 2 | 1 2 |
T3 | 不等待T1 结束,立即输出: No rows | 1 2 |
结论:
脏读、提交读在数据库并行访问上,提供了不同的隔离级别。在不同的情况下应该采用不一样的隔离级别。优缺点对比
访问策略 | 优点 | 缺点 |
脏读 DR | 不需要对查询的记录上锁,效率快。能提高数据的访问并发性。 | 查询数据出现现象:脏读、幻影数据 |
提交读 CR | 能有效防止脏读的出现 | 需要对查询记录加锁,以防止其他事务对所访问数据进行更新。访问效率较脏读低,同时大大降低了数据的访问并发性。多个事务间需要互相等待锁的释放,容易出现锁等待超时错误,导致事务失败。 |