MySQL夯实之路-事务详解

事务四大特性

事务需要通过严格的acid测试。Acid表示原子性,一致性,隔离性,持久性。

原子性(atomicity)

事务是不可分割的最小单元,对于整个事务的操作,要么全部提交成功,要么全部失败回滚。

一致性(consistency,最重要)

数据库总是从一个一致性的状态转换到另一个一致性的状态。要求几个事务并发执行的结果与串行顺序执行的结果一致。

隔离性(isolation)

通常,一个事务的修改在提交前对其它事务不可见。事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的(一个事务不会被另一个事务影响,最理想的就是等待一个事务执行完成后再执行另一个事务,但处于性能上的考虑,一般都需要事务并发执行,就要求事务执行过程中不受到并行执行的事务的影响,例如不能读取到另一个未提交(提交就是指事务执行完成)事务写入的值。

持久性(durability)

事务提交后,其修改永久保存在数据库中(但不可能有100%持久性保证)

原子性是基础,隔离性是手段,一致性是约束条件,目的是保持持久性。

隔离级别

Mysql标准中有四种隔离级别

未提交读

没有提交的事务的修改对其它事务可见。会发生脏读(事务读取未提交的数据)

提交读

没有提交的事务的修改对其它事务不可见,提交的事务的修改对其它事务可见。会发生不可重复度(两次执行相同查询可能结果不一样)

可重复读(innoDB默认)

在同一个事务上读取相同的记录的结果是一致的。会发生幻读(一个事务前后两次查询相同范围,后一次查询看到了前一次查询没有看到的行,原因是另一个事务中间插入了新的记录),innoDB和xtradb存储引擎通过了多版本并发控制(MVCC,multiversion concurrency control)解决了幻读问题

可串行化

在读取的每一行数据上加锁。避免了幻读,但导致了大量超时和锁争用问题

从上往下隔离级别越高,效率越低,越安全

MySQL夯实之路-事务详解_第1张图片

死锁

如果两个事务都获得了一把锁,双方又需要获取对方已经获得的锁,这时会发生死锁。

innoDB目前处理死锁的方法是,将持有最少行级排他锁的事务进行回滚

死锁的产生可能与存储引擎有关

事务日志

使用事务日志,存储引擎在修改表的数据时,只要修改其内存拷贝,再把修改行为记录到硬盘上的事务日志上,在后台再慢慢地刷回到磁盘。通常称为预写式日志(wal,write-ahead logging),先写入日志,再写入磁盘,修改数据需要写两次磁盘。

事务只要能记录到日志并持久化成功,系统崩溃也不会丢失

Mysql的事务

Mysql有两种事务型存储引擎innoDB,NDB Cluster。还有第三方的,如XtraDB PBXT

MySQL在开启事务时会切换到延缓操作的状态:操作并不会立刻执行,commit时才会执行并切换为自动提交状态,rollback时会将延缓操作丢弃,释放申请到的锁(关键),切换为自动提交状态。

自动提交(autocommit)

Mysql默认采用自动提交(autocommit)模式。即如果不是显示开启一个事务,每次查询默认为一个事务

Mysql服务器不管理事务,事务由存储引擎实现。在同一个事务中使用多个存储引擎是不可靠的(如果在事务中混合使用了事务型和非事务型得存储引擎,在回滚时非事务型表无法撤销,事务的最终结果不确定,难以修复),mysql事务型对非事务型表回滚时会警告,通常不会有提示

隐式和显式锁定

innoDB采用两阶段锁定协议。事务执行过程中随时可以执行锁定,只有在执行commit或者rollback时同时释放所有锁(前面描述的锁都是隐式的,innoDB会根据隔离级别在需要的时候自动加锁,也支持特定的语句进行显式锁定,但不属于sql规范,应该尽量避免)

Mysql也支持lock tables和unlock tables语句,但由服务器实现,和存储引擎无关,但并不用于事务处理,使用事务还是要使用事务型存储引擎(除了事务中禁用了autocommit,可以使用lock tables外,不要显式使用lock tables)

你可能感兴趣的:(mysql,mysql,数据库)