mysql-事务特性以及隔离机制

一.ACID

事务(Transaction)是访问和更新数据库的程序执行单元;事务中可能包含一个或多个sql语句,这些语句要么都执行,要么都不执行。

1.逻辑架构和存储引擎

mysql-事务特性以及隔离机制_第1张图片

 如上图所示,MySQL服务器逻辑架构从上往下可以分为三层:

(1)第一层:处理客户端连接、授权认证等。

(2)第二层:服务器层,负责查询语句的解析、优化、缓存以及内置函数的实现、存储过程等。

(3)第三层:存储引擎,负责MySQL中数据的存储和提取。MySQL中服务器层不管理事务,事务是由存储引擎实现的。MySQL支持事务的存储引擎有InnoDB、NDB Cluster等,其中InnoDB的使用最为广泛;其他存储引擎不支持事务,如MyIsam、Memory等。

***如无特殊说明,后文中描述的内容都是基于InnoDB

2. 提交和回滚

其中start transaction标识事务开始,commit提交事务,将执行结果写入到数据库。如果sql语句执行出现问题,会调用rollback,回滚所有已经执行成功的sql语句。当然,也可以在事务中直接使用rollback语句进行回滚。

3. ACID特性 

ACID是衡量事务的四个特性:

  • 原子性(Atomicity,或称不可分割性)
  • 一致性(Consistency)
  • 隔离性(Isolation)
  • 持久性(Durability)

按照严格的标准,只有同时满足ACID特性才是事务;但是在各大数据库厂商的实现中,真正满足ACID的事务少之又少。例如MySQL的NDB Cluster事务不满足持久性和隔离性;InnoDB默认事务隔离级别是可重复读,不满足隔离性;Oracle默认的事务隔离级别为READ COMMITTED,不满足隔离性……因此与其说ACID是事务必须满足的条件,不如说它们是衡量事务的四个维度。

二.隔离机制

1. 脏读 dirty read(读到未提交的数据)

解决办法:
方法1:事务隔离级别设置为:read committed。
方法2:读取时加排它锁(select…for update),事务提交才会释放锁,修改时加共享锁(update …lock in share mode)。加排它锁后,不能对该条数据再加锁,能查询但不能更改数据。mysql InnoDB引擎默认的修改数据语句,update,delete,insert都会自动给涉及到的数据加上排他锁,select语句默认不会加任何锁类型,如果加排他锁可以使用select …for update语句,如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁,共享锁下其它用户可以并发读取,查询数据。但不能修改,增加,删除数据。资源共享。
 

2.不可重复读 Non-Repeatable read(前后多次读取,数据内容不一致)

解决办法:
方法1:事务隔离级别设置为Repeatable read。
方法2:读取数据时加共享锁,写数据时加排他锁,都是事务提交才释放锁。读取时候不允许其他事物修改该数据,不管数据在事务过程中读取多少次,数据都是一致的,避免了不可重复读问题。

3. 幻读 repeatable read(前后多次读取,数据总量不一致)

解决办法:
        方法1:事务隔离级别设置为serializable ,那么数据库就变成了单线程访问的数据库,导致性能降低很多。
Isolation 属性一共支持五种事务设置,具体介绍如下:

        DEFAULT: 使用数据库设置的隔离级别 ( 默认 ) ,由 DBA 默认的设置来决定隔离级别 .

        READ_UNCOMMITTED: 会读到未提交的数据, 出现脏读、不可重复读、幻读 ( 隔离级别最低,并发性能高 )。

        READ_COMMITTED: 不会读到未提交的数据,会出现不可重复读、幻读问题(锁定正在读取的行)

        REPEATABLE_READ :会出幻读(锁定所读取的所有行)

        SERIALIZABLE :保证所有的情况不会发生(锁表)。

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