您的位置:首页 > 数据库

事务性质和隔离级别详解

2018-05-18 20:10 357 查看

事务定义

数据库事务(简称:事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。维基百科

事务性质 ACID

原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行

一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束

隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行

持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中

事务隔离级别

SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。维基百科

未提交读 [READ UNCOMMITTED]

提交读 [READ COMMITTED]

可重复读 [REPEATABLE READ]

可序列化 [Serializable]

默认隔离级别

不同的DBMS[database management system]默认隔离级别也不同。大多数据库允许用户设置隔离级别。有些DBMS在执行一个SELECT语句时使用额外的语法来获取锁(如SELECT ... FOR UPDATE来获得在访问的数据行上的排他锁)。

隔离级别 vs 读现象

隔离级别脏读不可重复读幻影读
未提交读 [READ UNCOMMITTED]可能发生可能发生可能发生
提交读 [READ COMMITTED]-可能发生可能发生
可重复读 [REPEATABLE READ]--可能发生
可序列化 [Serializable]---

隔离级别数据测试

MySQL 默认隔离级别

mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| **REPEATABLE-READ** |
+-----------------+
1 row in set (0.01 sec)

自动提交关闭:

mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set (0.00 sec)

修改隔离级别:

mysql>set session tx.isolation = 'READ-UNCOMMITTED';

具体测试方式:

A端操作不断改变 事务隔离级别,执行查询,B端不断进行数据更新操作

初始化数据:

use test;

CREATE TABLE `t_user` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
`name` varchar(255) DEFAULT '' COMMENT '姓名',
`age` int(3) DEFAULT NULL COMMENT '年龄',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`last_update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户测试表';

insert into t_user (name, age) values('小明',12);
insert into t_user (name, age) values('小李',13);
insert into t_user (name, age) values('小王',14);

READ-UNCOMMITTED 测试

A端操作B端操作
set session tx_isolation = 'READ-UNCOMMITTED';-
select * from t_users-
查询3条数据
begin;
insert into t_user(name,age) values('小花', 10);
select * from t_users-
查询4条数据-
-rollback;
select * from t_users-
查询3条数据-
总结:READ UNCOMMITTED会导致 脏读,不可重复读,幻读,是最低级的隔离级别,一般不用的。

READ COMMITTED 测试

A端操作B端操作
set session tx_isolation = 'READ-COMMITTED';-
select * from t_users-
查询3条数据-
-begin;
-insert into t_user(name,age) values('小花', 10);
select * from t_users-
查询3条数据-
-commit;
select * from t_users-
查询4条数据
总结:该隔离级别会导致不可重复读和幻读,避免了脏读,Oracle默认是该隔离级别。实际项目使用MyBaits时候虽然隔离级别是read committed,但是在一个事务中多次搜索还是会是同一个结果,这是因为MyBatis一级缓存的原因

REPEATABLE READ 测试

经过前面2个测试,目前已经包含4条数据

A端操作B端操作
set session tx_isolation = 'REPEATABLE-READ';
begin;-
select * from t_users;-
查询4条数据-
-begin;
-insert into t_user(name,age) values('小小', 6);
select * from t_users;-
查询4条数据(【未发生脏读】-
-commit;
select * from t_users;
查询4条数据(【可重复读】
commit;
select * from t_users-
查询5条数据-
总结:在一次事务中,当一行数据获取两遍得到不同的结果表示发生了“不可重复读”。前面A操作中,没用发生这种情况。该隔离级别为MySQL默认隔离级别。
REPEATABLE READ 可能引起幻影读的情况 MySQL 5.6 暂未出现

按照维基百科上的描述:

在可重复读(REPEATABLE READS)隔离级别中,基于锁机制并发控制的DBMS需要对选定对象的读锁(read locks)和写锁(write locks)一直保持到事务结束,但不要求“范围锁”,因此可能会发生“幻影读”。
当事务没有获取范围锁的情况下执行SELECT ... WHERE操作可能会发生“幻影读”。
“幻影读”是不可重复读的一种特殊场景:当事务1两次执行SELECT ... WHERE检索一定范围内数据的操作中间,事务2在这个表中创建了(如INSERT)了一行新数据,这条新数据正好满足事务1的“WHERE”子句

但我通过范围锁测试,并未出现幻读现象。

具体测试如下:

经过前面测试,目前已经包含5条数据

A端操作B端操作
set session tx_isolation = 'REPEATABLE-READ';
begin;-
select * from t_user where age between 10 and 20;-
查询4条数据(10~20共4条)-
-begin;
-insert into t_user(name,age) values('小六', 20);
-commit;
select * from t_user where age between 10 and 20;
查询4条数据(10~20共4条【未发生幻读】)
commit;
select * from t_users-
查询6条数据-

Serializable 测试

经过前面测试,目前已经包含6条数据

A端操作B端操作
set session tx_isolation = 'SERIALIZABLE';
begin;-
select * from t_user;-
查询5条数据-
-begin; insert into t_user(name,age) values('小七', 20);
一直处于等待状态【串行化执行】
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction 【串行化执行】
insert into t_user(name,age) values('小七', 20);
commit;
插入成功
select * from t_users-
查询6条数据【未发生脏读】【可重复读】-
commit;
select * from t_users-
查询7条数据-
总结:串行化隔离级别,就是多个事务串行化一个个按照顺序执行,这种不存在并发情况,所以可以避免所有事务并发问题。

参考:

/detail/2669567300.html

https://www.jianshu.com/p/249f2cd42692
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息