只有满足以下所有特点的SQL查询操作才建议显示开启Query Cache功能:写操作并不密集的数据表、读写操作比***大于10:1(或者根据读者自己的业务特性规定的更大比值)。毕竟只有业务层才清楚哪些数据表的读写操作比大于10:1,并且写操作并不时常进行。而满足以上操作特性的数据表通常都是基础性码表:例如行政区域表、电话分区表、身份证分区表、车辆号牌表。
对于复杂的SQL查询、读写比不大的数据表、写操作频繁或者写操作并发特别大的数据表并不建议开启Query Cache功能。例如订单表、库存物品表、车辆承运表、评论信息表等业务写操作频繁的数据表。
4-3、InnoDB中的锁虽然锁机制是InnoDB引擎中为了保证事务性而自然存在的,在索引、表结构、配置参数一定的前提下,InnoDB引擎加锁过程是一样的,所以理论上来说也就不存在“锁机制能够提升性能”这样的说法。但如果技术人员不理解InnoDB中的锁机制或者混乱、错误的索引定义和同样混乱的SQL写操作语句共同作用,那么导致死锁出现的可能性就越大,需要InnoDB进行死锁检测的情况就越多,最终导致不必要的性能浪费甚至事务执行失败。所以理解InnoDB引擎中的锁机制可以帮助我们在高并发系统中尽可能不让锁和死锁成为数据库服务的一个性能瓶颈。
4-3-1、InnoDB中的锁类型本文讲解的锁机制主要依据MySQL Version 5.6以及之前的版本(这是目前线上环境使用最多的版本),在MySQL Version 5.7以及最新的MySQL 8.0中InnoDB引擎的锁类型发生了一些变化(后文会提及),但基本思路没有变化。InnoDB引擎中的锁类型按照独占形式可以分为共享锁和排它锁(还有意向性共享锁和意向性排它锁);按照锁定数据的范围可以分为行级锁(其它引擎中还有页级锁的定义)、间隙锁、间隙复合锁??和表锁;为了保证锁的粒度能够至上而下传递,InnoDB中还设计有不能被用户干预的意向共享锁和意向排它锁。
共享锁(S锁)
由于InnoDB引擎支持事务,所以需要锁机制在多个事务同时工作时保证每个事务的ACID特性。共享锁的特性是多个事务可以同时为某个资源加锁后进行读操作,并且这些事务间不会出现相互等待的现象。
排它锁(X锁)
排它锁又被称为独占锁,一旦某个事务对资源加排它锁,其它事务就不能再为这个资源加共享锁或者排它锁了。一直要等待到当前的独占锁从资源上解除后,才能继续对资源进行操作。排它锁只会影响其他事务的加锁操作,也就是说如果其它事务只是使用简单的SELECT查询语句检索资源,就不会受到影响,因为这些SELECT查询语句不会试图为资源加任何锁,也就不会受资源上已有的排它锁的影响。我们可以用一张表表示排它锁和共享锁的互斥关系:
锁类型共享锁S排它锁X共享锁S 不互斥:多个共享锁不会相互影响相互等待 互斥:如果某个资源要加共享锁,则需要等待到资源上的排它锁配解除后,才能进行这个操作
排它锁X 互斥:如果资源要加排它锁,则需要等待到资源上所有共享锁都被解除后,才能进行这个操作 互斥:如果某个资源要加排它锁,则需要等待到资源上的排它锁配解除后,才能进行这个操作
排它锁和共享锁的互斥关系
行级锁(Record lock)
行级锁是InnoDB引擎中对锁的最小支持粒度,即是指这个锁可以锁定数据表中某一个具体的数据行,锁的类型可以是排它锁也可以是共享锁。例如读者可以在两个独立事务中同时使用以下语句查询指定的行,但是两个事务并不会相互等待:
# lock in share mode 是为满足查询条件的数据行加共享锁 # 注意它和直接使用select语句的不同特性 select * from myuser where id = 6 lock in share mode;间隙锁(GAP锁)
间隙锁只有在特定事务级别下才会使用,具体来说是“可重复读”(Repeatable Read )这样的事务级别,这也是InnoDB引擎默认的事务级别,它的大致解释是无论在这个事务中执行多少次相同语句的当前读操作,其每次读取的记录内容都是一样的,并不受外部事务操作的影响。间隙锁主要为了防止多个事务在交叉工作的情况下,特别是同时进行数据插入的情况下出现幻读。举一个简单的例子,事务A中的操作正在执行以下update语句的操作:
...... # 事务A正在执行一个范围内数据的更新操作 # 大意是说将用户会员卡号序列大于10的所有记录中user_name字段全部更新为一个新的值 update myuser set user_name = \'用户11\' where user_number >= 10; ......