运维 | 谈谈数据库事务隔离:为什么修改了我看不见
Posted 途牛技术中心
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了运维 | 谈谈数据库事务隔离:为什么修改了我看不见相关的知识,希望对你有一定的参考价值。
背景介绍
提到数据库事务,首先想到事务的4大特性--ACID
1、原子性(Atomicity)事务的操作要不全部成功 要不全部失败
2、一致性(Consistency)事务操作前后必须处于一致性的状态,例如拿转账来说,A和B两个用户账户共1000元,两个用户间转账前后总额还是1000元。
3、隔离性(Isolation)隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离
4、持久性(Durability)持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的
其中原子性、一致性、持久性这三种特性字面意思比较好理解,所以本次我们重点来说一说事务的隔离性。
01
数据库事务隔离
当数据库上有多个事务同时执行的时候,就可能出现脏读(dirty read)、不可重复读(non-repeatable read)、幻读(phantom read)的问题。
1、脏读(dirty read)一个事务处理过程里读取了另一个未提交的事务中的数据
2、不可重复读(non-repeatable read)数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了(修改)
3、幻读(phantom read)指一个事务读取到了另外一个事务中提交的insert的数据。
为了解决上面的问题,提出了隔离级别的概念,SQL标准的事务隔离级别包括:
1、读未提交(READ-UNCOMMITTED)一个事务还未提交,它做的变更即被其他事务看到 不常用
2、读提交(READ-COMMITTED)一个事务提交后,它所做的变更才被其他事务看到 常用
3、可重复读(REPEATABLE-READ)一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的。 常用
4、串行化(SERIALIZABLE)顾名思义是对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。 不常用
隔离级别 |
脏读(dirty read) |
不可重复读(non-repeatable read) |
幻读(phantom read) |
读未提交(READ-UNCOMMITTED) |
可能 |
可能 |
可能 |
读提交(READ-COMMITTED) |
不可能 |
可能 |
可能 |
可重复读(REPEATABLE-READ) |
不可能 |
不可能 |
可能 |
串行化(SERIALIZABLE) |
不可能 |
不可能 |
不可能 |
级别越高,数据越安全,但性能越低。常用的隔离级别包括读提交和可重复读,读未提交和串行化一般用的很少。
(Tips: 网上很多技术博文谈到事务隔离,经常使用RU、RC、RR这样的简写分别代表读未提交、读提交、可重复读)
02
MySQL事务隔离示例
注:如下所有说明均是基于mysql 5.6 InnoDB引擎
知识准备
MySQL中实现了SQL标准的事务隔离,MySQL默认的事务隔离级别是可重复读(每个数据库的默认事务隔离级别不同 Oracle的默认事务隔离级别是读提交)
在MySQL中查看事务隔离级别可以通过如下命令查看
MySQL 的事务启动方式有以下两种:
1、MySQL中默认事务提交是自动的 即:autocommit=1 ,如果需要显式启动事务语句, 使用begin 或 start transaction,配套的提交语句是 commit,回滚语句是 rollback。
2、set autocommit=0,这个命令会将这个会话的自动提交关掉。意味着如果你只执行一个 select 语句,这个事务就启动了,而且并不会自动提交。这个事务持续存在直到你主动执行 commit 或 rollback 语句,或者断开连接。
查看autocommit值
事务隔离实战
建立测试表,插入初始化数据
四种隔离级别测试
下面会通过MySQL中的实际案例来理解事务隔离下数据的可见性
可重复读
1、初始化数据
2、查看当前MySQL的事务隔离级别和事务启动方式,如上文提到的命令查看,
查看的结果
以上是关于运维 | 谈谈数据库事务隔离:为什么修改了我看不见的主要内容,如果未能解决你的问题,请参考以下文章