Mysql的事务有ACID四大特性,分别是原子性、一致性、隔离性、持久性。
- 原子性(atomicity):一个事物是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
实现原理:undo log实现事务的原子性,还用其实现多版本并发控制(MVCC)
undo log是逻辑日志(也是操作数据前的备份),可以理解为:
- 当delete一条记录时,undo log中会记录一条对应的insert记录
- 当insert一条记录时,undo log中会记录一条对应的delete记录
- 当update一条记录时,undo log中会记录一条对应的相反的update记录
其实,上面的说法是有点小问题的。实际上Mysql会根据逻辑计算出实际的值,而不需要在每个状态的时候都存储一份数据。
- 一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
- 隔离性(isolation):一个事物的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事物之间不能互相干扰。
SQL标准定义了4种隔离级别,高级别的隔离级别事务安全,并发性能较低,占用资源较多,低级别反之。
-
READ UNCOMMITTED(读未提交)
-
READ COMMITTED(读已提交)
-
REPEATABLE READ(可重复读)
-
SERIALIZABLE(可串行化)
MYSQL的默认事务隔离级别为repeatable-read
MySQL查看当前隔离级别和设置隔离级别:-- 查看隔离级别 mysql> show variables like 'tx_isolation'; -- 设置隔离级别 mysql> set global transaction isolation level READ UNCOMMITTED;
READ UNCOMMITTED(读未提交):即能够读取到没有被提交(commit)的数据,无法解决脏读、不可重复读、幻读中的任何一种,因此很少使用。
READ COMMITTED(读已提交):即能够读到那些已经提交的数据,自然能够防止脏读,但是无法限制不可重复读和幻读。
REPEATABLE READ(可重复读):即在数据读出来之后加锁,这个事务不结束,别的事务就不可以改这条记录,这样就解决了脏读、不可重复读的问题,但是幻读的问题还是无法解决。读已提交和可重复读的区别:
读已提交只要提交其他session就能查询到;可重复读,另一个session中,查询的数据不会发生变化。SERIALIZABLE(可串行化):最高的事务隔离级别,不管多少事务,挨个运行完一个事务的所有子事务之后才可以执行另外一个事务里面的所有子事务,这样就解决了脏读、不可重复读和幻读的问题了。读写操作会锁住整张表。
事务隔离级别解决的并发问题.png
- 持久性(durability):也成永久性(permanence),指一个事物一旦提交,它对数据库中的数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
实现原理:redo log,redo log是对新数据的备份,在事务提交前,只需将redo log持久化即可,不需要将数据持久化。当系统崩溃时,可以根据redo log 的内容将所有数据恢复到最新的状态。(发生了数据修改操作先写日志记录下来,等不忙的时候再持久化到磁盘)
举一个例子啊,有一个饭馆,生意非常好,忙不过来。某一天饭点特别忙,老王说老板把这顿饭钱给我记账上,那老板就得去账本里翻啊,找到老王再把账记上,但这样就忙不过来了。所以老板就找了个小黑板,在小黑板上记上老王的账。等到不忙了,再写到账本里去。
redo log是由两部分组成的:一是内存中的重做日志缓冲(redo log buffer);二是用来持久化的重做日志文件(redo log file)。所以为了消耗不必要的IO操作,事务再执行过程中产生的redo log首先会redo log buffer中,之后再统一存入redo log file刷盘进行持久化,这个动作成为fsync。
网友评论