大家好我是孙嵓,在家隔离一个周了快呆废了,该干点正事了走进高性能Mysql第二节课堂开课了。
Mysql中的事务
自动提交(AUTOCOMMIT)
Mysql默认采用自动提交(AUTOCOMMIT)模式即如果不是显式的开始一个事务,每个查询都被当作一个事务执行提交操作。可以通过设置AUTOCOMMIT变量来启用或者禁用自动提交模式,如图。
1或ON表示开启,0或OFF表示禁用。当其为0时,所有查询都在一个事务中,直到显式执行COMMIT或ROLLBACK,该事务结束,同时又开始另一个新事务。当然这对非事务表,例如MyISAM或者内存表不会有影响,因为他们本身就没有COMMIT或ROLLBACK概念,相当于一直处于AUTOCOMMIT启用模式。
此外还有一些命令在执行之前会强制执行COMMIT提交当前的活动事务,例如:DDL中ALTERTABLE。另外还有LCOKTABLES等其他语句也会导致同样的结果。Mysql可通过执行SETTRANSACTIONISOLATIONLEVEL命令来设置隔离级别。新的隔离级别会在下一个事务开始的时候生效。可在配置文件中设置整个数据库的隔离级别,也可以只改变当前会话的隔离级别语句如下SETSESSIONTRANSACTIONISOLATIONLEVELREADCOMMITED;
事务中混合使用存储引擎
那我们思考下一个问题如果说一个事务中混合使用存储引擎会怎样。我们知道事务都是由Mysql下层的存储引擎实现。所以在同一个事务中,使用多种存储引擎是不可靠的。假如我们事务中混合使用了事务型和非事务型的表(例如InnoDB和MyISAM表),正常提交情况下不会有什么问题。但如果事务需要回滚,非事务型的表上的变更就无法撤销,这会导致数据库处于不一致的状态,这种情况就很难修复了,所以每张表选择合适的存储引擎很重要。
隐式和显式锁定
InnoDB采用的是两阶段锁定协议(two-phaselockingprotocol)。在事务执行过程中,随时都可执行锁定,锁只有在执行COMMIT或ROLLBACK的时候才会释放,且所有锁都在同一时刻被释放,上述为隐式锁定,InnoDB会根据隔离级别在需要时候自动加锁。此外InnoDB也支持通过特定的语句进行显示锁定,这些语句并不属于SQL规范。SELECT...LCOKINSHAPEMODESELECT...FORUPDATE
显示的使用诸如LOCKTABLES语句完全没必要还影响性能,不如InnoDB的存储引擎。
总只一句话,如果应用需要事务就应该选择事务型存储引擎。
多版本并发控制(MVCC,MultiversionConcurrencyContral)
划重点啊,面试题经常问。Mysql的大多事务型存储引擎实现的都不是简单的行级锁,一般都同时实现了多版本并发控制(MVCC)。不仅Mysql,Oracle、PostgreSQL等其他数据库也都实现了MVCC,各自实现机制不尽相同,因此MVCC没有一个统一的实现标准。Mysql的MVCC可以看为是行级锁一个变种,在很多情况下避免了加锁操作,开销更低。虽然实现机制有所不同,但大都实现了非阻塞的读操作,写操作也只锁定必要的行。MVCC是通过保存数据在某个时间点的快照来实现。不同存储引擎MVCC实现不同,典型的有乐观(optimistic)并发和悲观(pessimistic)并发控制。下面我们讲解一下简化版InnoDB的MVCC的工作流程。InnoDB的MVCC,通过每行记录后面保存两个隐藏的列来实现。这两列一个保存了行的创建时间,一个保存行的过期时间(或删除时间),存储的不是实际的时间值而是一个系统版本号(应该有个规则其中一部分就是时间戳我猜测)。事务开始时的版本号做为事务的版本号,用来和查询到的每行记录的版本号做比较,看一下REPEATABLEREAD隔离级别下,MVCC具体如何操作的:有了这两列可以避免大多数操作都可以不用加锁,这样设计很明显读数据操作简单,性能很好。不足的地方每行记录多加两列需要额外的存储空间,需要更多的行检查工作以及额外的维护工作。注意:MVCC只在REPEATABLEREAD和READCOMMITED两个隔离级别工作,可以联想一下啊READUNCOMMITED总是读取最新的数据行,不符合MVCC思想,而SERIALIZABLE会对所有读取的行都加锁。
Mysql的存储引擎
重点又来了,本节对各种存储引擎做一个简单的概述。文件系统中,Mysql将每个数据库保存为数据目录下的一个子目录。创建表时,Mysql会在数据库子目录下创建一个和表同名的.frm文件保存表的定义。我们可以通过SHOWTABLESTATUS命令显示表的相关信息,例如下图mysql的user表:这是个MyISAM表,我们看下每一行的含义。
InnoDB
InnoDB采用MVCC支持高并发,实现了四个标准的隔离级别,默认级别为REPEATABLEREAD(可重复读),并且通过间隙锁(next-keylocking)策略防止幻读的出现。间隙锁使得InnoDB不仅仅锁定查询涉及的行,还会对索引中的间隙进行锁定,来防止幻影行的插入。InnoDB是基于聚簇索引建立的,索引及优化在后续文章单独讲。聚簇索引对主键查询有很高的性能,聚簇索引也称为主键索引。它的二级索引(secondaryindex,非主键索引)包含主键列,所以主键列很大的话,其他所有索引都会很大。若表上的索引较多的话,主键应当尽可能的小。InnoDB内部做很多优化,包括从磁盘读取数据时采用的可预测性读,能够在动在内存中创建hash索引以加速读操作的自适应哈希索引(adaptivehashindex),以及能够加速插入操作的插入缓冲区(insertbuffer)等。支持真正的在线热备份。其它存储引擎不支持在线热备份,要获取一致性视图需要停止对所有表的写入,而在读写混合场景中,停止写入可能也意味着停止读取。来自