深入浅出剖析 MySQL 事务及索引

mysql中的事务

mysql默认采用自动提交模式,也就是说,如果不是明显地开始一个事务,每个查询都会被当做一个事务执行提交操作,在当前连接中,可以通过设置AUTOCOMMIT变量来启动或者禁用自动提交模式,1表示启动。

事务的ACID特性

事务的原子性是指事务内的语句要么全部执行,要么全部执行失败。

事务的一致性是指数据库总是从一个一致性的状态转移到另外一个一致性的状态。

事务的隔离性是指一个事务在最终提交以前,对其他的事务是不可见的。

事务的持久性是指一旦事务被提交,则其所做的修改会永久保存到数据库中

事务的隔离级别

未提交读(Read Uncommitted)

读写均不使用锁,数据的一致性最差,也会出现许多逻辑错误。在未提交读级别中,事务中的修改,没有提交,对其他事务也都是可见的,事务可以读取未提交的数据,造成脏读。

提交读(Read Committed)

使用写锁,但是读会出现不一致,造成不可重复读(两次读取不一致)。提交读是大多数数据库系统默认的隔离级别,但MySQL不是,具体是指一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。举例说明就是对于一个数A由50修改成100,另一个事务在A提交修改之前,读取到了A是50,刚读取完,A就被修改成了100,再次读取就变成100。

可重复读(Repeatable Read)

使用读锁和写锁,解决不可重复读的问题,但会有幻读,幻读是指当某个事务在读取某个范围内的记录时另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行。InnoDB通过加间隙锁的方式解决了幻读的问题。间隙锁就是锁住了所有的行避免其他的事务改变A 中的变量。总结来说就是在可重复读的隔离级别下存在幻读的可能性,但是MySQL的InnoDB通过加间隙锁的方式解决了幻读。MySQL引擎的默认级别是可重复读。

可串行化(Serializable)

可串行化是最高的隔离级别,它通过强制事务串行执行,避免了前面说的幻读的问题,简单说就是可串行化会在每一行的数据上都加锁,所以可能导致大量的超时和锁争用的问题。

隔离级别 脏读可能性 不可重复读可能性 幻读可能性
未提交读 YES YES YES
提交读 NO YES YES
可重复读 NO NO YES
串行化 NO NO NO

索引

索引一般是放在磁盘中的,索引是存储引擎用于快速找到记录的一种数据结构。索引优化应该是对查询优化最有效的手段了。索引能够轻易将查询性能提高几个数量级,创建一个最优的索引经常需要重写查询。索引可以包含一个或多个列的值,如果索引包含多个列,那么列的顺序也十分重要,因为MySQL只能高效地使用索引的最左前缀。创建一个包含两个列的索引,和创建两个包含只包含一列的索引是大不相同的。

哈希索引

哈希索引基于哈希表实现,只有精确匹配索引所有列的查询才有效。对于每一行的数据,存储引擎都会对所有的索引列计算一个哈希码,哈希码是较小的值,并且不同键值的计算出来的哈希码也不一样。哈希索引将所有的哈希码存储在索引中,同时在哈希表中保存指向每一个数据行的指针。