赞
踩
数据持久化:将内存的数据保存到硬盘上
目前使用最多的 DBMS 分别是 Oracle、 MySQL 和 SQL Server。这些都是关系型数据库(RDBMS)。
Oracle 更适合大型跨国企业的使用,因为他们对费用不敏感,但是对性能要求以及安全性有更高的要求。
MySQL 由于其体积小、速度快、总体拥有成本低,可处理上千万条记录的大型数据库,尤其是开放源码这一特点,使得很多互联网公司、中小型网站选择了MySQL作为网站数据库。
关系型数据库(RDBMS):以 行(row) 和 列(column) 的形式存储数据,以便于用户理解。这一系列的行和列被称为 表(table) ,一组表组成了一个库(database)
非关系型数据库:可看成传统关系型数据库的功能阉割版本 ,基于键值对存储数据,不需要经过SQL层的解析, 性能非常高 。同时,通过减少不常用的功能,进一步提高性能
关系型数据库的典型数据结构就是 数据表 ,这些数据表的组成都是结构化的(Structured)。
将数据放到表中,表再放到库中。
一个数据库中可以有多个表,每个表都有一个名字,用来标识自己。表名具有唯一性。
表具有一些特性,这些特性定义了数据在表中如何存储,类似Java和Python中 “类”的设计。
SQL语言在功能上主要分为如下3大类:
DDL(Data Definition Languages、数据定义语言),这些语句定义了不同的数据库、表、视图、索引等数据库对象,还可以用来创建、删除、修改数据库和数据表的结构。
主要的语句关键字包括 CREATE 、 DROP 、 ALTER 等。
DML(Data Manipulation Language、数据操作语言),用于添加、删除、更新和查询数据库记录,并检查数据完整性。
主要的语句关键字包括 INSERT 、 DELETE 、 UPDATE 、 SELECT 等。
SELECT是SQL语言的基础,最为重要。
DCL(Data Control Language、数据控制语言),用于定义数据库、表、字段、用户的访问权限和安全级别。
主要的语句关键字包括 GRANT 、 REVOKE 、 COMMIT 、 ROLLBACK 、 SAVEPOINT 等。
关于标点符号
规范:
1、MySQL 在 Linux 环境下是大小写敏感的
2、推荐采用统一的书写规范:
作用:为了管理方便,人们把连接管理、查询缓存、语法解析、查询优化这些不涉及真实数据存储的功能划分为MySQL server的功能,把真实存取数据的功能划分为存储引擎(表处理器)的功能
在MySQL server完成了查询优化后,只需按照生成的执行计划调用底层存储引擎提供的API,获取到数据后返回给客户端,
存储引擎的功能就是接收上层传下来的指令,对表中数据进行提取或写入操作
优势:
事务
,是MySQL默认事务型引擎,用来处理大量短期事务,确保事务的完整提交和回滚外键
约束:MySQL支持外键的存储引擎只有InnoDB。行级锁
应用:
特点:
应用:
对于count(*),查询效率高(专门存储了这个字段)
索引:是帮助MySQL高效获取数据的数据结构(排好序的快速查找数据结构)
索引是存储引擎快速找到数据记录的一种数据结构(进行查询操作时,首先查看查询条件是否命中某条索引,符合则通过索引查找相关数据;不符合则需要全表扫描,一条一条去查找,直到找到符合条件的记录)
按物理实现方式,分为聚簇索引和非聚簇索引(又称二级索引、辅助索引)
按功能逻辑分,普通索引、唯一性索引(UNIQUE)、主键索引(特殊的唯一性索引,NOT NULL + UNIQUE)、全文索引
按作用字段个数分,单列索引、联合索引
一种数据存储方式(所有的用户记录都存储在叶子节点)
索引即数据,数据即索引
InnoDB存储引擎自动创建聚簇索引
只有搜索条件是主键值时才能发挥作用(因为B+树的顺序都是按照主键值排序的)
特点:
1、使用记录主键值的大小进行记录和页的排序
2、B+树的叶子节点存储的是完整的用户记录(包括隐藏列)
3、目录项记录主键+页号
优点:
缺点:
以非主键值列建立的索引(索引条件为非主键值列)
特点:
1、使用记录c2列的大小进行记录和页的排序
2、B+树叶子结点存储的不是完整的用户记录,只有c2列+主键这2个列的值
3、目录项记录c2列+页号的值
缺点:找到目标列值,拿到主键后,需要再去聚簇索引查找具体的行数据(称为回表)
属于非聚簇索引的一种
以多个非主键值列建立的索引(索引条件多个非主键值列)
最左前缀原则
特点:
1、使用记录c2列的大小和记录c3列的大小进行记录和页的排序
2、B+树叶子结点存储的不是完整的用户记录,只有c2列+c3列+主键这3个列的值
3、目录项记录c2列+c3列+页号的值
缺点:找到目标列值,拿到主键后,需要再去聚簇索引查找具体的行数据(称为回表)
InnoDB索引即数据
MyISAM将索引和数据分开存储(索引仅仅保存数据记录的地址,一定存在回表)
在实际工作中也需要注意平衡,索引的数目不是越多越好。要限制每张表上的索引数目,建议单张表索引数量不超过6个,原因:
1.每个索引都需要占用磁盘空间,索引越多,需要的磁盘空间就人。
2.索引会影响INSERT、DELETE、UPDATE等语句的性能,因为表中的数据更改的同时,索引也会进行调整和更新,会造成负担。
3.优化器在选择如何优化查询时,会根据统一信息,对每一个可以用到的索引进行评估,以生成出一个最好的执行计划,如果同时有很多个
索引都可以用于查询,会增加MySQL优化器生成执行计划时间,降低查询性能
索引本身可以起到约束的作用,比如唯一索引、主键索引都是可以起到唯一性约束的,因此在我们的数据表中,如果某个字段是唯一性的,就可以直接创建唯一性索引,或者主键索引。这样可以更快速地通过该索引来确定某条记录。
某个字段在SELECT语句的 WHERE 条件中经常被使用到,那么就需要给这个字段创建索引了。尤其是在数据量大的情况下,创建普通索引就可以大幅提升数据查询的效率。
索引就是让数据按照某种顺序进行存储或检索,因此当我们使用 GROUP BY 对数据进行分组查询,或者使用 ORDER BY 对数据进行排序的时候,就需要 对分组或者排序的字段进行索引 。如果待排序的列有多个,那么可以在这些列上建立 组合索引。
总结:
对数据按照某个条件进行查询后再进行 UPDATE 或 DELETE 的操作,如果对 WHERE 字段创建了索引,就能大幅提升效率。原理是因为我们需要先根据 WHERE 条件列检索出来这条记录,然后再对它进行更新或删除。如果进行更新的时候,更新的字段是非索引字段,提升的效率会更明显,这是因为非索引字段更新不需要对索引进行维护。
有时候我们需要对某个字段进行去重,使用 DISTINCT,那么对这个字段创建索引,也会提升查询效率。
首先,连接表的数量尽量不要超过 3 张,因为每增加一张表就相当于增加了一次嵌套的循环,数量级增长会非常快,严重影响查询的效率。
其次, 对 WHERE 条件创建索引 ,因为 WHERE 才是对数据条件的过滤。如果在数据量非常大的情况下,没有 WHERE 条件过滤是非常可怕的。
最后, 对用于连接的字段创建索引 ,并且该字段在多张表中的 类型必须一致 。比如 course_id 在student_info 表和 course 表中都为 int(11) 类型,而不能一个为 int 另一个为 varchar 类型。
这里所说的类型大小指的就是该类型表示的数据范围的大小。
在定义表结构的时候要显式的指定列的类型,以整数类型为例,有TINYINT、MEDIUNINT、INT、BIGINT等,它们占用的存储空间依次递增,能表示的整数范围当然也是依次递增。如果想要对某个整数列建立索引的话。在表示的整数范围允许的情况下,尽量让索引列使用较小的类型,比如能使用INT就不要使BIGINT,能使用MEDIUMINT就不要使用INT。这是因为:
这个建议对于表的主键来说更加适用,因为不仅是聚簇索引中会存储主键值,其他所有的二级索引的节点处都会存储一份记录的主键值,如果主键使用更小的数据类型,也就意味着节省更多的存储空间和更高效的I/O。
假设字符串很长,那存储一个字符串就需要占用很大的存储空间。在需要为这个字符串列建立索引时,那就意味若在对应的B+树中有这么两个问题:
我们可以通过截取字段的前面一部分内容建立索引,这个就叫前缀索引。这样在查找记录时虽然不能精确的定位到记录的位置,但是能定位到相应前缀所在的位置,然后根据前缀相同的记录的主键值回表查询完整的字符串值。既节约空间,又减少了字符串的比较时间,还大体能解决排序的问题。
列的基数: 指的是某一列中不重复数据的个数,比方说某个列包含值2,5,8,2,5,8,2,5,8,虽然有9条记录,但该列的基数却是3。也就是说,在记录行数一定的情况下,列的基数越大,该列中的值越分散;列的基数越小,该列中的值越集中。这个列的基数指标非常重要,直接影响我们是否能有效的利用索引。最好为列的基数大的列建立索引,为基数太小列的建立索引效果可能不好。
可以使用公式 select count(distinct a)/count(*) from t1计算区分度,越接近1越好,一般超过33%就算是比较高效的索引了。
这样也可以较少的建立一些索引。同时,由于"最左前缀原则",可以增加联合索引的使用率
WHERE条件(包括GROUP BY、ORDER BY)里用不到的字段不需要创建索引,索引的价值是快速定位,如果起不到定位的字段通常是不需要创建索引的。
如果表记录太少,比如少于1000个,那么是不需要创建索引的。表记录太少,是否创建索引对查询效率的影响并不大。甚至说,查询花费的时间可能比遍历索引的时间还要短,索引可能不会产生优化效果。
第一层含义︰频繁更新的字段不一定要创建索引。因为更新数据的时候,也需要更新索引,如果索引太多,在更新索引的时候也会造成负担,从而影响效率。
第二层含义:避免对经常更新的表创建过多的索引,并且索引中的列尽可能少。此时,虽然提高了查询速度,同时却会降低更新表的速度。
例如身份证、UUID(在索引比较时需要转为ASCII,并且插入时可能造成页分裂)、MD5、HASH、无序长字符串等。
表中的数据被大量更新,或者数据的使用方式被改变后,原有的一些索引可能不再需要。数据库管理员应当定期找出这些索引,将它们删除,从而减少索引对更新操作的影响
有时候有意或者无意的就对同一个列创建了多个索引,比如: index(a,b,c)相当于index(a)、index(a,b)、index(a,b,c)。
InnoDB将数据划分为若干页,页的默认大小是16KB,页是磁盘和内存交互的基本单位,是数据库IO操作的最小单位
按类型分:数据页(保存B+树节点,包括叶子节点和非叶子节点)、系统页、Undo、事务数据页
索引设计的问题
JOIN表过多问题
数据表设计问题
服务器参数配置的问题
需要增加缓存的问题
解决步骤图解:
value为查询的页数
先删除,再生成空的日志文件
1、 show profiles
得到SQL编号信息3
2、定位执行慢的操作
executing-分析具体的SQL语句
定位了查询慢的SQL之后,就可以用EXPLAIN或者DESCRIBE工具做针对性的分析查询语句(查看查询语句的具体执行计划),帮助我们有针对性的提升查询语句的性能
数据库调优的维度:
SQL查询优化分为:
MySQL中提高性能最有效的方式是对数据表设计合理的索引(快速定位表中的某条记录,如果没有使用索引,查询语句就会扫描表中所有的记录)
其实,用不用索引,最终是优化器决定的,它是基于cost开销、不是基于规则,也不是基于语义。另外,SQL语句是否使用索引,跟数据库版本、数据量、数据选择度都有关系。
了解即可
首先理解驱动表和被驱动表:
总结:
join方式连接多个表,本质就是各个表之间数据的循环匹配。MySQL5.5 版本之前,MySQL只支持一种表间关联方式,就是嵌套循环(Nested Loop Join)。如果关联表的数据量很大,则join关联的执行时间会非常长。在MySQL5.5以后的版本中,MySQL通过引入BNLJ算法来优化嵌套执行。从MySQL的8.0.20版本开始将废弃BNLJ
,因为从MySQL8.0.18版本开始就加入了hash join默认都会使用hash join
算法相当简单,从表A中取出一条数据1,遍历表B,将匹配到的数据放到result…以此类推,驱动表A中的每一条记录与被驱动表B的记录进行判断
Index Nested-Loop Join其优化的思路主要是为了减少内层表数据的匹配次数,所以要求被驱动表上必须有索引
才行。通过外层表匹配条件直接与内层表索引进行匹配,避免和内层表的每条记录去进行比较,这样极大的减少了对内层表的匹配次数。
如果存在索引,那么会使用index的方式进行join,如果join时被驱动表的列没有索引
,被驱动表要扫描的次数太多了。每次访问被驱动表,其表中的记录都会被加载到内存中,然后再从驱动表中取一条与其匹配,匹配结束后清除内存,然后再从驱动表中加载一条记录,然后把被驱动表的记录在加载到内存匹配,这样周而复始,大大增加了IO的次数。为了减少被驱动表的IO次数,就出现了Block Nested-Loop Join的方式。
不再是逐条获取驱动表的数据,而是一块一块的获取,引入了join buffer缓冲区,将驱动表join相关的部分数据列(大小受join buffer的限制)缓存到join buffer中,然后全表扫描被驱动表,被驱动表的每一条记录一次性和join buffer中的所有驱动表记录进行匹配(内存中操作),将简单嵌套循环中的多次比较合并成一次,降低了被驱动表的访问频率
注意:
这里缓存的不只是关联表的列,select后面的列也会缓存起来。
在一个有N个join关联的sql中会分配N-1个join buffer。所以查询的时候尽量减少不必要的字段,可以让join buffer中可以存放更多的列。
总结:
1. 整体效率比较: INLJ > BNLJ > SNLJ
2. 永远用小结果集驱动大结果集(其本质就是减少外层循环的数据数目) (小的度量单位指的是表行数*每行大小)
3. 为被驱动表匹配的条件增加索引(减少内层表的循环匹配次数)
4. 增大join buffer size的大小(一次缓存的数据越多,那么内层包的扫表次数就越少)
5. 减少驱动表不必要的字段查询(字段越少,join buffer所缓存的数据就越多)
6. 保证被驱动表的J0IN字段已经创建了索引
7. 需要JOIN的字段,数据类型保持绝对一致
8. LEFT JOlN时,选择小表作为驱动表,大表作为被驱动表。减少外层循环的次数。INNER JOIN时,MySQL会自动将小结果集的表选为驱动表。选择相信MySQL优化策略
9. 能够直接多表关联的尽量直接关联,不用子查询(减少查询的趟数)
10. 不建议使用子查询,建议将子查询SQL拆开结合程序多次查询,或使用JOIN来代替子查
11. 衍生表建不了索引
Nested Loop:
对于被连接的数据子集较小的情况,Nested Loop是个较好的选择。
Hash Join是做大数据集连接
时的常用方式,优化器使用两个表中较小(相对较小)的表利用Join Key在内存中建立散列表,然后扫描较大的表并探测散列表,找出与Hash表匹配的行
Hash Join只能应用于等值连接
(如WHERE A.COL1=B.COL2),这是由Hash的特点决定的MySQL从4.1版本开始支持子查询,使用子查询可以进行SELECT语句的嵌套查询,即一个SELECT查询的结果作为另一个SELECT语句的条件。子查询可以一次性完成很多逻辑上需要多个步骤才能完成的SQL操作。
问题:
子查询是MySQL的一项重要的功能,可以通过一个SQL语句实现比较复杂的查询。但是,子查询的执行效率不高
。
原因:
① 执行子查询时,MySQL需要为内层查询语句的查询结果建立一个临时表
,然后外层查询语句从临时表中查询记录。查询完毕后,再撤销这些临时表。这样会消耗过多的CPU和IO资源
,产生大量的慢查询
② 子查询的结果集存储的临时表,不论是内存临时表还是磁盘临时表都不会存在索引
,所以查询性能会受到一定的影响
③ 对于返回结果集比较大的子查询。其对查询性能的影响也就越大
解决:
在MySQL中,可以使用连接(JOIN)查询来替代子查询
。连接查询不需要建立临时表,其速度比子查询要快,如果查询中使用索引
的话,性能就会更好。
尽量不要使用NOT IN 或者 NOT EXISTS,用LEFT JOIN xxx ON xx WHERE xx IS NULL替代
解答:
在MySQL中,支持两种排序方式,分别是FileSort
和Index
排序。
在内存中进行排序
,占用CPU 较多。如果待排结果较大,会产生临时文件I/O到磁盘进行排序的情况,效率校低filesort: 通过表的索引或全表扫描,读取满足条件的数据行,然后在排序缓冲区sort buiffer中完成排序操作,所有不是通过索引直接返回排序结果的排序都叫FileSot 排序
。
index: 通过有序索引
顺序扫描直接返回有序数据,这种情况即为using index,不需要额外排序,操作效率高
优化建议:
① SQL中,可以在WHERE子句和ORDER BY子句中使用索引,目的是在WHERE子句中避免全表扫描
,在ORDER EY子句避免使用 FileSort排序
。当然,某些情况下全表扫描,或者FileSort排序不一定比索引慢。但总的来说,还是要避免,以提高查询效率。
② 尽量使用Index完成ORDER BY排序
。如果WHERE和ORDER BY后面是相同的列就使用单索引列;如果不同就使用联合索引
③ 无法使用lndex时,需要对FileSort方式进行调优
经验总结:
INDEX a_b_c(a,b,c) order by 能使用索引最左前缀 - ORDER BY a - ORDER BY a,b - ORDER BY a,b,c - ORDER BY a DESC,b DESC,c DESC - 如果WHERE使用索引的最左前缀定义为常量,则order by 能使用索引 - WHERE a = const ORDER BY b,c - WHERE a = const AND b = const ORDER BY c - WHERE a = const ORDER BY b,c - WHERE a = const AND b > const ORDER BY b,c - 不能使用索引进行排序 - ORDER BY a ASC,b DESC,c DESC /* 排序不一致 */ - WHERE g = const ORDER BY b,c /*丢失a索引*/ - WHERE a = const ORDER BY c /*丢失b索引*/ - WHERE a = const ORDER BY a,d /*d不是索引的一部分*/ - WHERE a in (...) ORDER BY b,c /*对于排序来说,多个相等条件也是范围查询*/
结论:
问题:
EXPLAIN select * from student limit 2000000,10;
一般分页查询时,通过创建覆盖索引能够比较好地提高性能。一个常见又非常头疼的问题就是limit 2000000,10,此时需要MySQL排序前2000010记录,仅仅返回2000000-2000010的记录,其他记录丢弃,查询排序的代价非常大。
在大数据量的分页查询时,limit后的起始位置越靠后,耗时越长
解决:
① 在索引上完成排序分页操作,最后根据主键关联回原表查询所需要的其他列内容。
EXPLAIN SELECT * FROM student t,(SELECT id FROM student ORDER BY id LIMIT 2000000,10) a WHERE t.id = a.id;
② 该方案适用于主键自增的表,可以把Limit查询转换成某个位置的查询
EXPLAIN SELECT * FROM student WHERE id > 2000000 LIMIT 10;
总结:
limit优化思路:通过覆盖索引+子查询的方式来优化
尽量使用覆盖索引(覆盖索引:查询使用了索引,并且需要返回的列,在该索引中已经全部能够找到),减少使用selecl *.
覆盖索引: SQL只需要通过索引就可以返回查询所需要的数据
,而不必通过二级索引查到主键之后再去查询数据
理解方式一: 索引是高效找到行的一个方法,但是一般数据库也能使用索引找到一个列的数据,因此它不必读取整个行。毕竟索引叶子节点存储了它们索引的数据;当能通过读取索引就可以得到想要的数据,那就不需要读取行了。一个索引包含了满足查询结果的数据就叫做覆盖索引。
理解方式二: 非聚簇复合索引的一种形式,它包括在查询里的SELECT、JOIN和WHERE子句用到的所有列(即建索引的字段正好是覆盖查询条件中所涉及的字段)。
简单说就是, 索引列+主键 包含 SELECT 到 FROM之间查询的列
。
当单机上的表的设计和SQL优化已经做到极限,在高并发的场景下,考虑多个服务器
库级优化是站在数据库的维度上进行的优化策略,比如控制一个库中的数据表数量。另外,利用外援的方式,通过主从架构
优化我们的读写策略,通过对数据库垂直或水平切分,突破单一数据库或数据表的访问限制,提升查询的性能
对于需要经常联合查询的表,可以建立中间表以提高查询效率。
把需要经常联合查询的数据插入中间表中,然后将原来的联合查询改为对中间表的查询,以此提高查询效率
注意:涉及数据的修改时,需要修改两张表的数据(常用的做法是对原表进行修改时,删除中间表重新建立)
优先选择存储需要的最小的数据类型
针对InnoDB引擎:
一张数据表的表结构所符合的某种设计标准的级别
数据库三范式:
1)、符合1NF的关系中的每个属性都不可再分。
2)、2NF在1NF的基础之上,消除了非主属性对于码的部分函数依赖。
3)、3NF在2NF的基础之上,消除了非主属性对于码的传递函数依赖。
4)、BCNF在3NF的基础之上,消除主属性对于码的部分与传递函数依赖。
一些前置概念:
超键:能唯一标识元组的属性集(理解:候选键加任意键的集合)
候选键
:可唯一标识元组的属性,可以有多个(又称码
)
主键:选取候选键中的任意一个(又称主码)
外键:如果表1中的某个属性不是表1的主键,而是表2的主键,那这个属性就是表1的外键
主属性:包含在任一候选键中的属性
非主属性:不包含在任一候选键中的属性
1NF的定义为:符合1NF的关系中的每个属性都不可再分。
问题:依赖关系大,对数据的操作不灵活
消除了非主属性对于码的部分函数依赖
理解:
满足数据表中的每一条数据记录,都是可唯一标识的,而且所有非主键字段,都必须完全依赖候选键(码),不能只依赖候选键(码)的一部分
案例:
解决方案:
总结:
1NF告诉我们字段属性需要时原子性的,而2NF告诉我们一张表就是一个独立的对象,一张表只表达一个意思
消除了非主属性对于码的传递函数依赖。
理解:第三范式是在第二范式的基础上,确保数据表中的每一个非主键字段都和主键字段(候选键)直接相关,要求表中的所有非主键字段不能依赖于其他非主键字段(所有非主键属性之间不能有依赖关系
,必须相互独立)
总结:每个非主键属性依赖于主键,依赖于整个主键,并且除了主键别无他物
BCNF被认为没有新的设计规范加入,只是对第三范式中设计规范要求更强,使得数据库冗余度更小,称为是修正的第三范式或扩充的第三范式
BCNF:一个关系达到了第三范式,并且它只有一个候选键,或者它的每个候选键都是单属性
一般来说,一个数据库设计符合3NF或BCNF即可
问题:
使用经验:
当冗余信息有价值或者能大幅度提高查询效率时,才会采取反范式优化
原子性Atomicity:事务是不可分割的整体(undo log日志)
一致性Consistency:事务执行前后状态合法(undo log日志)
隔离性Isolation:事务之间相互独立(锁机制和MVCC快照读 )
持久性Durability:事务提交后持久化到数据库(redo log日志(先写日志再修改数据库))
最终状态要么是提交的(刷盘)要么是终止的(回滚)
理解:
读未提交、读已提交、可重复读、序列化。
事务的隔离性由锁机制实现
事务的原子性、一致性、持久性由事务的redo日志和undo日志来保证
redo log称为重做日志,提供再写入操作,恢复提交事务修改的页操作,用来保证事务的持久性
undo log称为回滚日志,回滚行记录到某个特定版本,用来保证事务的原子性和一致性
redo的整体流程:
多版本并发控制
:multi-version concurrency control,主要是为了提高数据库的并发性能,不用去竞争锁,针对读已提交和可重复读
同一行数据平时发生读写请求时,会上锁阻塞住,但mvcc用更好的方式去处理读写请求,做到在发生读写请求冲突时不用加锁
这个读是指快照读
,而不是当前读,当前读是一种加锁操作,是悲观锁。
undo log
版本链
readview
:判断回滚到版本链的哪一条记录(判断版本链中哪个版本可用),在代码里通常为一个对象
读已提交
:每个select查询时生成一个readview
,
如果2个select语句在一个事务中,当执行到第二个select时刚好update事务提交了,那么2次查询的结果就是不一致的,即没有实现可重复读可重复读
:每个事务生成一个readview
,
一个事务中无论有几个select语句,都是共用一个readview,从而实现可重复读。
m_ids:没有commit的事务列表
min_trx_id:m_ids中最小的事务id
max_trx_id:系统中即将分配的事务id
creator_trx_id:生成readview的事务的事务id
判断逻辑
:
可以访问:trx_id == creator_trx_id 在版本链内
可以访问:trx_id < min_trx_id 已经提交的事务
不可访问:trx_id > max_trx_id 超出版本链
min_trx_id <= trx_id <= max_trx_id:如果trx_id在m_ids中(未提交),不可访问,反之可以访问(已提交)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。