Transaction Isolation Levels(事务隔离级别):
事务隔离是数据库处理的基础之一,Isolation代表ACID原则的"I"。当多个事务对同一记录进行修改或查询的时候,事务隔离级别很好的协调了性能和可靠性、一致性和查询结果的复制性的关系。
Transaction Isolation Levels提供4种隔离级别(按级别由低到高排列):
(1),READ_UNCOMMITED(脏读)
使用不加锁的方式执行查询语句,查询语句有可能查询到上一次快照的数据,意味着,在这种事务隔离级别下,数据库读取是不一致的,也就是平常说的dirty read,脏读。除此之外,其他的特性和READ_COMMITED一致。
(2),READ_COMMITED(提交读)
每一次一致性读取,即使是在同一个事务内,设置并读取当次读取维护的最新快照。 对于Locking read(SELECT
with FOR UPDATE
or LOCK IN SHARE MODE
),Update,Delete语句来说,只对索引覆盖到的记录进行加锁。而不是索引数据之前的间隙。因此允许其他事务在索引记录周围自由进行插入。在READ_COMMITED事务隔离级别下,gap locks仅仅在外键约束检查和重复主键检查才使用。此种事务隔离级别有可能会导致记录丢失,如果此时其他事务也在同一位置插入数据并提交成功。
READ_COMMITED只支持row-based binary logging。
a,对于UPDATE和DELETE语句,InnoDB
只持有待更新或删除数据的锁,当Mysql评估Where后的查询条件后,会释放掉不匹配where condition 条件的记录。这种机制会大大减少死锁的次数,但还是有可能发生死锁。
b,对于UPDATE语句,如果一条记录已经被加锁,InnoDB
会执行“semi-consistent”读取,返回最新提交的版本给Mysql,Mysql会评估当前记录行是否符合where condition,如果匹配,mysql会重新读取当前记录并进行加锁或等待加锁;
(3),REPEATABLE_READ(可重复读)
Innodb默认事务隔离级别,同一个事务内的一致性读,只读取事务内首次读取(select语句)创建的快照,也就是说同一事务内随后的读取行为(Plain Select),和首次读获取的数据是一致的,无论这期间其他的事务有没有提交数据。
对于Locking read(SELECT
with FOR UPDATE
or LOCK IN SHARE MODE
),Update,Delete语句来说,是否加锁,取决于SQL语句中(unique search condition (此处我理解为指定查询(例如 select * from table1 where id = b))或者 range_type search condition(>, < ,>=, <=, in, between))是否使用了unique index(唯一索引),如果使用了唯一索引,则加锁,否则不加锁。
a,对于使用唯一索引的指定查询,Innodb只对索引覆盖到的查询数据进行加锁,而不是之前的gap(间隙);
b,对于其他的查询,Innodb使用gap locks或者next-key locks对索引覆盖到的范围进行加锁,以此阻止其他事务在索引覆盖到的范围内插入数据。
(4),SERIALIZABLE(序列化读)
这种隔离级别类似REPEATABLE_READ,如果未设置autocommit = 0, mysql会暗中将所有简单的select语句转化为(SELECT
with FOR UPDATE
or LOCK IN SHARE MODE
)。如果设置了autocommit = 1,则只会将当前事务所在的SELECT转为(SELECT
with FOR UPDATE
or LOCK IN SHARE MODE
)。因此,当执行一致性读取的时候,只能读取数据并被序列化而不需要阻塞其他事务。
以上内容,纯属个人总结,如有不正确的地方,请予以指正!