事务
作者:互联网
ACID 的含义
说到事务,大家第一反应是 Theo Härder 和 Andreas Reuter 于 1983 提出的 ACID。虽然 ACID 最初提出是为了为数据库中的容错保证给出一种相对精确的描述,但不同数据库对 ACID 的支持并不相同,尤其是 Isolation —— 隔离性。如今,ACID 更多的沦为一个 PR 术语。
下面,将逐一探究 Atomicity、Consistency、Isolation 和 Durability 的精确含义,以此来对事务所要做出的保证建立一个基本的认识。
原子性(Atomicity)
“原子”一般指最小单位,不可再分。在并发编程中,原子性通常和可见性关联,即一个线程无法看到另一个线程执行的原子操作的中间结果。
一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成。
一致性( Consistency)
在事务开始之前和事务结束以后,数据库的完整性没有被破坏。
隔离性(Isolation)
多个客户端并发访问数据库时,如果访问的数据没有交集,是可以随意并发的。但如果有交集,则会产生并发问题,或称竞态条件(race condition)。
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交(Read uncommitted) | 可能 | 可能 | 可能 |
读已提交(Read committed) | 不可能 | 可能 | 可能 |
可重复读(Repeatable read) | 不可能 | 不可能 | 可能 |
可串行化(Serializable ) | 不可能 | 不可能 | 不可能 |
事务隔离级别的描述
1、读未提交(Read uncommitted)
在一个事务a执行过程中可以读取到其它事务中编辑后的数据,尽管其它事务还没有提交。
当事务a中读取到了事务b编辑后的数据后,事务b做了回滚操作。那么事务a读取到的数据就是脏数据(脏读);
当事务a在执行过程中对同一条查询语句执行了多次,但由于事务b在事务a多次查询过程中新增(insert)了数据,造成事务a多次查询的结果不一致,那么事务a的多次查询结果不一致的情况就是幻读;
当事务a在执行过程中对同一条查询语句执行了多次,但由于事务b在事务a多次查询过程中修改(update)或者删除(delete)了数据,造成事务a多次查询的结果不一致,那么事务a的多次查询结果不一致的情况就是不可重复读;
2、读已提交(Read committed)
在一个事务a执行过程中可以读取到其它事务编辑并提交(commit)后的数据,如果其它事务没有提交,则获取不到。
当事务a在执行过程中对同一条查询语句执行了多次,但由于事务b在事务a多次查询过程中修改(update)或者删除(delete)了数据,造成事务a多次查询的结果不一致,那么事务a的多次查询结果不一致的情况就是不可重复读;
在将MySql的事务隔离级别改为读已提交(Read committed)的时候,需要修改my.cnf配置文件,将二进制日志(bin log)存储格式改成ROW。并且隔离锁将失效。
3、可重复读(Repeatable read)
是MySql的默认事务隔离级别,在一个事务a执行过程中对同一条查询sql语句执行结果都是一样的,不受其它事务的影响。
当事务a在执行过程中对同一条查询语句执行了多次,但由于事务b在事务a多次查询过程中新增(insert)了数据,造成事务a多次查询的结果不一致,那么事务a的多次查询结果不一致的情况就是幻读;
where 范围操作的时候会产生隔离锁。 例如:update student set name = '小王' where id > 5 and id < 10;
隔离锁锁住的是id小于5的哪条数据 至 id大于10之间的数据。例如id在表中的值有(1,2,20,30),那么上面的sql语句锁住的范围未2 - 20之间。对于insert的隔离锁没有这种限制。
可使用(排他锁)for update或者共享锁(lock in share mode)来避免幻读:select * from table where id = 1 for update ; 或者select * from table where id = 1 lock in share mode;
4、可串行化(Serializable )
于可重复度(Repeatable read)比较接近,当autocommit被禁用后,innodb存储引擎会将每个select语句后面都加上 lock in share mode(共享锁);
持久性(Durability)
持久性是一种保证,即事务一旦提交,即使服务器宕机重启、甚至发生硬件故障,已经提交的事务所写入的数据就不会丢失。
在单机数据库中,持久性意味着以数据页(Page)或日志形式(WAL)写入了非易失性存储。在多副本(Replication)数据库中,持久性意味着写入了多数节点。
但,持久性都只能做到某种程度的保证,而非绝对保证,比如:
- 对于单机,可以容忍宕机。但磁盘坏了就完犊子。
- 对于多机,可以容忍少数副本损坏,但是多数副本完后也没辙。
因为在现实世界中,存储所涉及到的所有环节,都不是完美的:
- 写入磁盘后宕机,虽然数据没丢,但机器修复或磁盘转移前,数据服务都是不可用的。但冗余(Replication)系统可以解决该问题。
- 一个关联性故障,如软件 bug 或者机房断电,可以同时摧毁一个机房中的所有副本。因此多副本的内存数据库仍要定期持久化到外存。
- 异步复制系统中,当主副本不可用时,由于没来得及同步到多数节点,最近的写入主副本成功的数据可能会丢失。
- 当突然断电时,固态硬盘可能不能保证数据已完整刷盘,甚至用户显式调用 fsync 也无济于事。此外,硬盘驱动可能也会有 bug。
- 磁盘上的数据可能会随着时间逐渐损坏,甚至副本数据也可能同时损坏,此时就只能依赖于备份了。
在实践中,要通过多种手段,比如强制刷盘、校验码、异地复制、定时备份等多种手段来保证数据的持久性,但也只能做到大概率的保证(比如五个九),而非绝对保证。
标签:事务,隔离,多次,查询,数据,id 来源: https://www.cnblogs.com/tortoise512/p/16367636.html