【MySQL入门】之细说脏读、幻读及不可重复读
一、事务的基本要素(ACID)
ACID原则是数据库事务正常执行的四个基本要素,分别指原子性、一致性、隔离性及持久性。
原子性(Atomicity)是指一个事务要么全部执行,要么不执行,也就是说一个事务不可能只执行了一半就停止了,比如A转账给B 100元,这个事务可以分成两个步骤:第一步A账户扣除100元,第二步B账户增加100元。不可能出现A账户扣钱,而B账户未增加钱的情况,这两步必须同时完成,任何一步出现问题整个事务就会回滚。
一致性(Consistency)是指事务的运行并不改变数据库中数据的一致性。事务开始之前,数据库处于一致性的状态;事务结束后,数据库必须仍处于一致性状态。数据库一致性的定义是由用户负责的。例如,上面的例子中,A和B的账户金额之和在转账前后要保持不变。
隔离性(Isolation):事务的隔离性,是指两个以上的事务不会出现交错执行的状态,因为这样可能会导致数据不一致。
持久性(Durability):一旦事务提交或者回滚,这个状态都要持久化到数据库中。
二、事务的提交和回滚
#事务的提交
mysql> start transaction;#手动开启事务
mysql> insert into t_test(name) values(‘jack’);
mysql> commit;#commit代表事务提交
mysql> select * from t_test;
+----+------+
| id | name |
+----+------+
| 1 | herry|
| 2 | jack |
+----+------+
2 rows in set (0.00 sec)
#事务的回滚
mysql> start transaction;#手动开启事务
mysql> insert into t_test(name) values(‘jack’);
mysql> rollback;#代表事务回滚
mysql> select * from t_test;
+----+------+
| id | name |
+----+------+
| 1 | herry|
+----+------+
1 rows in set (0.00 sec)
三、数据库事务的隔离级别
数据库事务的隔离级别有4个,由低到高依次为Read uncommitted 、Read committed 、Repeatable read 、Serializable ,这四个级别可以逐个解决脏读 、不可重复读 、幻读这几类问题。
隔离级别 |
脏读 |
不可重复读 |
幻读 |
---|---|---|---|
读未提交(Read uncommitted) |
可能 |
可能 |
可能 |
读已提交(Read committed) |
不可能 |
可能 |
可能 |
可重复读(Repeatable read) |
不可能 |
不可能 |
可能 |
序列化(Serializable) |
不可能 |
不可能 |
不可能 |
1. Read UnCommitted(读未提交)
最低的隔离级别。一个事务可以读取另一个事务并未提交的更新结果。生产环境不建议使用。
2. Read Committed(读提交)
一个事务的更新操作结果只有在该事务提交之后,另一个事务才可以的读取到同一笔数据更新后的结果。这种情况也叫不可重复读,允许幻读的发生,是oracle数据库的默认隔离级别。
3. Repeatable Read(重复读)
mysql的默认级别。整个事务过程中,对同一笔数据的读取结果是相同的,不管其他事务是否在对共享数据进行更新,也不管更新提交与否。避免了脏读、不可重复读和幻读的发生。
4. Serializable(序列化)
最高隔离级别。所有事务操作依次顺序执行。会导致大量的超时以及锁竞争,同时导致并发度下降,性能最差。不建议生产使用。
四、不同事务级别带来的并发问题
1.脏读
脏读发生在一个事务A读取了被另一个事务B修改,但是还未提交的数据。假如B回退,则事务A读取的是无效的数据。
如上图所示,t3时刻,事务A读取到了事务B累加5但是还未提交的a值,且在t3时刻,事务B回滚了,那么事务A基于t3时刻的查询所做的操作就会出现问题。
2.不可重复读
事务A前后读取到的数据不一致。
如上图所示,事务A在t2时刻读取到a的值,和t4时刻读取到的a的值不一致,因为事务B在t3时刻对a值进行了更新并提交
3.幻读
幻读发生在当两个完全相同的查询执行时,第二次查询所返回的结果集跟第一次查询不相同。
如上图所示,事务A在t2时刻和t4时刻获取到的数据条数不一致,因为事务B在t3时刻新增了一条符合事务A查询条件的数据并提交了,事务A像是出现了幻觉一样。
五、总结
今天我们主要一起学习了事务的特性、隔离级别以及不同隔离级别会引发的问题。事务的这些特性主要是通过日志技术、锁技术以及MVCC(多版本并发控制)来一起实现的,后面我们会逐一掀起它们的盖头来。
- MySQL 教程
- MySQL 安装
- MySQL 管理与配置
- MySQL PHP 语法
- MySQL 连接
- MySQL 创建数据库
- MySQL 删除数据库
- MySQL 选择数据库
- MySQL 数据类型
- MySQL 创建数据表
- MySQL 删除数据表
- MySQL 插入数据
- MySQL 查询数据
- MySQL where 子句
- MySQL UPDATE 查询
- MySQL DELETE 语句
- MySQL LIKE 子句
- mysql order by
- Mysql Join的使用
- MySQL NULL 值处理
- MySQL 正则表达式
- MySQL 事务
- MySQL ALTER命令
- MySQL 索引
- MySQL 临时表
- MySQL 复制表
- 查看MySQL 元数据
- MySQL 序列 AUTO_INCREMENT
- MySQL 处理重复数据
- MySQL 及 SQL 注入
- MySQL 导出数据
- MySQL 导入数据
- MYSQL 函数大全
- MySQL Group By 实例讲解
- MySQL Max()函数实例讲解
- mysql count函数实例
- MYSQL UNION和UNION ALL实例
- MySQL IN 用法
- MySQL between and 实例讲解
- php实现根据身份证获取精准年龄
- php 使用ActiveMQ发送消息,与处理消息操作示例
- php使用gearman进行任务分发操作实例详解
- laravel框架select2多选插件初始化默认选中项操作示例
- PHP pthreads v3在centos7平台下的安装与配置操作方法
- laravel框架路由分组,中间件,命名空间,子域名,路由前缀实例分析
- PHP Beanstalkd消息队列的安装与使用方法实例详解
- 解决windows上php xdebug 无法调试的问题
- php7 图形用户界面GUI 开发示例
- Django开发的简易留言板案例详解
- php使用redis的有序集合zset实现延迟队列应用示例
- PHP使用openssl扩展实现加解密方法示例
- php使用redis的几种常见操作方式和用法示例
- 使用memory_profiler监测python代码运行时内存消耗方法
- php 多进程编程父进程的阻塞与非阻塞实例分析