转载于网络

这几天在读《MySQL技术内幕 InnoDB存储引擎》,对 Innodb逻辑存储结构有了些了解,顺便也记录一下;

从InnoDB存储引擎的逻辑存储结构看,所有数据都被逻辑地存放在一个空间中,称之为表空间(tablespace)。表空间又由段(segment)、区(extent)、页(page)组成。页在一些文档中有时也称为(block),InnoDB存储引擎的逻辑存储结构大致如图:

一、表空间

表空间可以看做是InnoDB存储引擎逻辑结构的最高层,所有的数据都存放在表空间中。默认情况下InnoDB存储引擎有一个共享表空间ibdata1,即所有数据都存放在这个表空间内。如果用户启动了innodb_file_per_table,则每个表内的数据可以单独放到一个表空间内,但要注意的是每张表的表空间内存放的只是数据、索引和插入缓存Bitmap页,而其他类的数据,如回滚(undo)信息,插入缓存索引页、系统事务信息、二次写缓存(Double write buffer)等还是存放在原来的共享表空间内。

现在想说明一个问题的就是,即使设置了innodb_file_per_table为ON了,共享表空间还是会不断地增加其大小,以下做个实验来验证下:

(1)下面看看初始共享表空间的大小

  1. root@localhost [wjqtest]>show variables like 'innodb_file_per_table';
  2. +-----------------------+-------+
  3. | Variable_name | Value |
  4. +-----------------------+-------+
  5. | innodb_file_per_table | ON |
  6. +-----------------------+-------+
  7. 1 row in set (0.11 sec)
  8. root@localhost [wjqtest]>system ls -lh /data/mysql/mysql_3306/data/ibdata*
  9. -rw-r----- 1 mysql mysql 76M Jul 28 17:43 /data/mysql/mysql_3306/data/ibdata1

可以看到:共享表空间的大小ibdata1的大小为76M,接着模拟undo的操作,利用mytest1数据表,并把其存储引擎更改为innodb,执行结果如下所示:

(2)首选将自动提交设置为off,即用户需要显示的提交事务

  1. root@localhost [wjqtest]>show variables like 'autocommit';
  2. +---------------+-------+
  3. | Variable_name | Value |
  4. +---------------+-------+
  5. | autocommit | ON |
  6. +---------------+-------+
  7. 1 row in set (0.03 sec)
  8. root@localhost [wjqtest]>set autocommit=0;
  9. Query OK, 0 rows affected (0.10 sec)
  10. root@localhost [wjqtest]>show variables like 'autocommit';
  11. +---------------+-------+
  12. | Variable_name | Value |
  13. +---------------+-------+
  14. | autocommit | OFF |
  15. +---------------+-------+
  16. 1 row in set (0.00 sec)

(3)下面的更新操作并没有执行commit或rollback,该操作会产生大量的undo,然后在观察共享表空间的大小

  1. root@localhost [wjqtest]>update mytest1 set salary=0;
  2. Query OK, 2621440 rows affected (16.68 sec)
  3. Rows matched: 2621440 Changed: 2621440 Warnings: 0

(4)发现ibdata1由原来的76M增长到了140M,这足以说明共享表空间中还包含undo的信息

  1. root@localhost [wjqtest]>system ls -lh /data/mysql/mysql_3306/data/ibdata*
  2. -rw-r----- 1 mysql mysql 140M Jul 28 17:46 /data/mysql/mysql_3306/data/ibdata1

(5)由于上面的事务没有提交,那么执行回滚操作,ibdata1表空间的大小是不是会将到原来的大小呢?

  1. root@localhost [wjqtest]>rollback;
  2. Query OK, 0 rows affected (53.65 sec)
  3. root@localhost [wjqtest]>system ls -lh /data/mysql/mysql_3306/data/ibdata*
  4. -rw-r----- 1 mysql mysql 140M Jul 28 17:56 /data/mysql/mysql_3306/data/ibdata1

通过上面的实验测试发现:共享表空间的大小依旧是140M,即说明innodb存储引擎不会再执行rollback的时候去收缩共享表空间的大小;虽然innodb不会回收这些空间,但是会自动判断这些undo信息是否还需要,如果不需要,则会将这些空间标记为可用空间,供下次undo使用;

二、段

上图中显示了表空间是由各个段组成的,常见的段有数据段、索引段、回滚段等。InnoDB存储引擎表是索引组织的(index organized),因此数据即索引,索引即数据。那么数据段即为B+树的页节点(上图的leaf node segment),索引段即为B+树的非索引节点(上图的non-leaf node segment)。

与Oracle不同的是,InnoDB存储引擎对于段的管理是由引擎本身完成,这和Oracle的自动段空间管理(ASSM)类似,没有手动段空间管理(MSSM)的方式,这从一定程度上简化了DBA的管理。
需要注意的是,并不是每个对象都有段。因此更准确地说,表空间是由分散的页和段组成。

三、区

区是由连续的页组成的空间,在任何的情况下每一个区的大小都是1M。为了保证区中页的连续性,innodb存储引擎一次从磁盘申请4~5个区。默认的情况下,innodb存储引擎也的大小为16K,即一个区中一共有64个连续的页。

Innodb1.2.X版本新增了参数innodb_page_size,通过该参数可以将默认的页的大小设置为4K、8K,但是页中的数据是不压缩的。总之,不论页的大小如何的变化,区的大小总是1M;

在我们启用了参数innodb_file_per_talbe后,创建的表默认大小是96KB。区是64个连续的页,那创建的表的大小至少是1MB才对啊?其实这是因为在每个段开始时,先有32个页大小的碎片页(fragment page)来存放数据,当这些页使用完之后才是64个连续页的申请。这样做的目的是,对于一些小表,或undo这类的段,可以在开始时申请较少的空间,节省磁盘容量的开销。

下面通过一个小的实验来显示innodb存储引擎对于区的申请方式:

(1)创建测试表t1

  1. root@localhost [wjqtest]>create table t1(col1 int not null auto_increment primary key,col2 varchar(7000));
  2. Query OK, 0 rows affected (0.26 sec)
  3. root@localhost [wjqtest]>system ls -lh /data/mysql/mysql_3306/data/wjqtest/t1.ibd;
  4. -rw-r----- 1 mysql mysql 96K Jul 28 18:26 /data/mysql/mysql_3306/data/wjqtest/t1.ibd

创建了t1表,col2字段设为varchar(7000),这样能保证一个页中可以存放2条记录。可以看到,初始创建完t1后表空间默认大小为96KB.

(2)接着插入两条数据,根据之前对表的定义,这两条记录应该位于同一个页中,然后通过py_innodb_page_info.py工具来查看表空间

  1. root@localhost [wjqtest]>insert t1 select null,repeat('a',7000);
  2. Query OK, 1 row affected (0.19 sec)
  3. Records: 1 Duplicates: 0 Warnings: 0
  4. root@localhost [wjqtest]>insert t1 select null,repeat('a',7000);
  5. Query OK, 1 row affected (0.03 sec)
  6. Records: 1 Duplicates: 0 Warnings: 0
  7. root@localhost [wjqtest]>system ls -lh /data/mysql/mysql_3306/data/wjqtest/t1.ibd;
  8. -rw-r----- 1 mysql mysql 96K Jul 28 18:31 /data/mysql/mysql_3306/data/wjqtest/t1.ibd

下面使用py_innodb_page_info小工具(py_innodb_page_info小工具),用来查看表空间中各页的类型和信息。

  1. [root@VM_35_215_centos py_innodb_page_type]# python py_innodb_page_info.py -v /data/mysql/mysql_3306/data/wjqtest/t1.ibd
  2. page offset 00000000, page type
  3. page offset 00000001, page type
  4. page offset 00000002, page type
  5. page offset 00000003, page type , page level <0000>
  6. page offset 00000000, page type
  7. page offset 00000000, page type
  8. Total number of page: 6:
  9. Freshly Allocated Page: 2
  10. Insert Buffer Bitmap: 1
  11. File Space Header: 1
  12. B-tree Node: 1
  13. File Segment inode: 1

如上结果,这次用-v来查看详细的表空间的内容,注意到了page offset为3的页,这个就是数据页。Page level表示所在的索引层,0表示叶子节点。因为当前所有就都在一个页中,因此没有非叶子节点。但是如果这是用户在插入一条记录,就会产生一个非叶节点:

  1. root@localhost [wjqtest]>insert t1 select null,repeat('a',7000);
  2. Query OK, 1 row affected (0.05 sec)
  3. Records: 1 Duplicates: 0 Warnings: 0
  4. root@localhost [wjqtest]>system ls -lh /data/mysql/mysql_3306/data/wjqtest/t1.ibd;
  5. -rw-r----- 1 mysql mysql 96K Jul 28 18:35 /data/mysql/mysql_3306/data/wjqtest/t1.ibd
  6. [root@VM_35_215_centos py_innodb_page_type]# python py_innodb_page_info.py -v /data/mysql/mysql_3306/data/wjqtest/t1.ibd
  7. page offset 00000000, page type
  8. page offset 00000001, page type
  9. page offset 00000002, page type
  10. page offset 00000003, page type , page level <0001>
  11. page offset 00000004, page type , page level <0000>
  12. page offset 00000005, page type , page level <0000>
  13. Total number of page: 6:
  14. Insert Buffer Bitmap: 1
  15. File Space Header: 1
  16. B-tree Node: 3
  17. File Segment inode: 1

如上执行结果,现在可以看到page offset为3的页的page level由之前的0变成了1,这时虽然新插入的记录导致B+树的分裂操作,但是这个页的类型还是B-tree Node。

接着继续上述同样的操作,在插入60条记录,也就是说当前t1中共有63条记录,32个页。为了导入的方便,在这之前先建立一个导入的存储过程:

  1. root@localhost [wjqtest]>delimiter //
  2. root@localhost [wjqtest]>
  3. root@localhost [wjqtest]>create procedure load_t1(count int unsigned)
  4. -> begin
  5. -> declare s int unsigned default 1;
  6. -> declare c varchar(7000) default repeat('a',7000);
  7. -> while s <= count do -> insert into t1 select null,c;
  8. -> set s=s+1;
  9. -> end while;
  10. -> end;
  11. -> //
  12. delimiter ;Query OK, 0 rows affected (0.48 sec)
  13. root@localhost [wjqtest]>delimiter ;
  14. root@localhost [wjqtest]>call load_t1(60);
  15. Query OK, 1 row affected (0.34 sec)
  16. root@localhost [wjqtest]>select count(*) from t1;
  17. +----------+
  18. | count(*) |
  19. +----------+
  20. | 63 |
  21. +----------+
  22. 1 row in set (0.00 sec)
  23. root@localhost [wjqtest]>system ls -lh /data/mysql/mysql_3306/data/wjqtest/t1.ibd;
  24. -rw-r----- 1 mysql mysql 592K Jul 28 18:46 /data/mysql/mysql_3306/data/wjqtest/t1.ibd

由上面的执行结果可以看到,在导入了63条数据后,表空间的大小还是小于1M,即表示数据空间的申请还是通过碎片页,而不是通过64个连续页的区。这时候在通过py_innodb_page_info.py工具来观察一下表空间t1.ibd

  1. [root@VM_35_215_centos py_innodb_page_type]# python py_innodb_page_info.py -v /data/mysql/mysql_3306/data/wjqtest/t1.ibd
  2. page offset 00000000, page type
  3. page offset 00000001, page type
  4. page offset 00000002, page type
  5. page offset 00000003, page type , page level <0001>
  6. page offset 00000004, page type , page level <0000>
  7. page offset 00000005, page type , page level <0000>
  8. page offset 00000006, page type , page level <0000>
  9. page offset 00000007, page type , page level <0000>
  10. page offset 00000008, page type , page level <0000>
  11. page offset 00000009, page type , page level <0000>
  12. page offset 0000000a, page type , page level <0000>
  13. page offset 0000000b, page type , page level <0000>
  14. page offset 0000000c, page type , page level <0000>
  15. page offset 0000000d, page type , page level <0000>
  16. page offset 0000000e, page type , page level <0000>
  17. page offset 0000000f, page type , page level <0000>
  18. page offset 00000010, page type , page level <0000>
  19. page offset 00000011, page type , page level <0000>
  20. page offset 00000012, page type , page level <0000>
  21. page offset 00000013, page type , page level <0000>
  22. page offset 00000014, page type , page level <0000>
  23. page offset 00000015, page type , page level <0000>
  24. page offset 00000016, page type , page level <0000>
  25. page offset 00000017, page type , page level <0000>
  26. page offset 00000018, page type , page level <0000>
  27. page offset 00000019, page type , page level <0000>
  28. page offset 0000001a, page type , page level <0000>
  29. page offset 0000001b, page type , page level <0000>
  30. page offset 0000001c, page type , page level <0000>
  31. page offset 0000001d, page type , page level <0000>
  32. page offset 0000001e, page type , page level <0000>
  33. page offset 0000001f, page type , page level <0000>
  34. page offset 00000020, page type , page level <0000>
  35. page offset 00000021, page type , page level <0000>
  36. page offset 00000022, page type , page level <0000>
  37. page offset 00000023, page type , page level <0000>
  38. page offset 00000000, page type
  39. Total number of page: 37:
  40. Freshly Allocated Page: 1
  41. Insert Buffer Bitmap: 1
  42. File Space Header: 1
  43. B-tree Node: 33
  44. File Segment inode: 1

如上的执行结果:可以看到B-tree node页一共有33个,除去一个page level为1的非叶节点叶,一共有32个page level为0的页,也就是说,对于数据段,已经有32个碎片页了。之所以用户在申请空间,则表空间按连接64个页的大小开始增长了

接下来,在插入一条数据,查看插入之后表空间的大小

  1. root@localhost [wjqtest]>call load_t1(1);
  2. Query OK, 1 row affected (0.02 sec)
  3. root@localhost [wjqtest]>system ls -lh /data/mysql/mysql_3306/data/wjqtest/t1.ibd;
  4. -rw-r----- 1 mysql mysql 2.0M Jul 28 18:52 /data/mysql/mysql_3306/data/wjqtest/t1.ibd

因为已经用完了32个碎片页,新的页会采用区的方式进行空间的申请,如果此时用户在使用py_innodb_page_info.py工具开查看表空间文件t1.ibd,应该可以看到很多类型为Freshly Allocated Page的页,如下所示:

  1. [root@VM_35_215_centos py_innodb_page_type]# python py_innodb_page_info.py -v /data/mysql/mysql_3306/data/wjqtest/t1.ibd
  2. page offset 00000000, page type
  3. page offset 00000001, page type
  4. page offset 00000002, page type
  5. page offset 00000003, page type , page level <0001>
  6. page offset 00000004, page type , page level <0000>
  7. page offset 00000005, page type , page level <0000>
  8. page offset 00000006, page type , page level <0000>
  9. page offset 00000007, page type , page level <0000>
  10. page offset 00000008, page type , page level <0000>
  11. page offset 00000009, page type , page level <0000>
  12. page offset 0000000a, page type , page level <0000>
  13. page offset 0000000b, page type , page level <0000>
  14. page offset 0000000c, page type , page level <0000>
  15. page offset 0000000d, page type , page level <0000>
  16. page offset 0000000e, page type , page level <0000>
  17. page offset 0000000f, page type , page level <0000>
  18. page offset 00000010, page type , page level <0000>
  19. page offset 00000011, page type , page level <0000>
  20. page offset 00000012, page type , page level <0000>
  21. page offset 00000013, page type , page level <0000>
  22. page offset 00000014, page type , page level <0000>
  23. page offset 00000015, page type , page level <0000>
  24. page offset 00000016, page type , page level <0000>
  25. page offset 00000017, page type , page level <0000>
  26. page offset 00000018, page type , page level <0000>
  27. page offset 00000019, page type , page level <0000>
  28. page offset 0000001a, page type , page level <0000>
  29. page offset 0000001b, page type , page level <0000>
  30. page offset 0000001c, page type , page level <0000>
  31. page offset 0000001d, page type , page level <0000>
  32. page offset 0000001e, page type , page level <0000>
  33. page offset 0000001f, page type , page level <0000>
  34. page offset 00000020, page type , page level <0000>
  35. page offset 00000021, page type , page level <0000>
  36. page offset 00000022, page type , page level <0000>
  37. page offset 00000023, page type , page level <0000>
  38. page offset 00000000, page type
  39. page offset 00000000, page type
  40. page offset 00000000, page type
  41. page offset 00000000, page type
  42. page offset 00000000, page type
  43. page offset 00000000, page type
  44. page offset 00000000, page type
  45. page offset 00000000, page type
  46. page offset 00000000, page type
  47. page offset 00000000, page type
  48. page offset 00000000, page type
  49. page offset 00000000, page type
  50. page offset 00000000, page type
  51. page offset 00000000, page type
  52. page offset 00000000, page type
  53. page offset 00000000, page type
  54. page offset 00000000, page type
  55. page offset 00000000, page type
  56. page offset 00000000, page type
  57. page offset 00000000, page type
  58. page offset 00000000, page type
  59. page offset 00000000, page type
  60. page offset 00000000, page type
  61. page offset 00000000, page type
  62. page offset 00000000, page type
  63. page offset 00000000, page type
  64. page offset 00000000, page type
  65. page offset 00000000, page type
  66. page offset 00000040, page type , page level <0000>
  67. page offset 00000000, page type
  68. page offset 00000000, page type
  69. page offset 00000000, page type
  70. page offset 00000000, page type
  71. page offset 00000000, page type
  72. page offset 00000000, page type
  73. page offset 00000000, page type
  74. page offset 00000000, page type
  75. page offset 00000000, page type
  76. page offset 00000000, page type
  77. page offset 00000000, page type
  78. page offset 00000000, page type
  79. page offset 00000000, page type
  80. page offset 00000000, page type
  81. page offset 00000000, page type
  82. page offset 00000000, page type
  83. page offset 00000000, page type
  84. page offset 00000000, page type
  85. page offset 00000000, page type
  86. page offset 00000000, page type
  87. page offset 00000000, page type
  88. page offset 00000000, page type
  89. page offset 00000000, page type
  90. page offset 00000000, page type
  91. page offset 00000000, page type
  92. page offset 00000000, page type
  93. page offset 00000000, page type
  94. page offset 00000000, page type
  95. page offset 00000000, page type
  96. page offset 00000000, page type
  97. page offset 00000000, page type
  98. page offset 00000000, page type
  99. page offset 00000000, page type
  100. page offset 00000000, page type
  101. page offset 00000000, page type
  102. page offset 00000000, page type
  103. page offset 00000000, page type
  104. page offset 00000000, page type
  105. page offset 00000000, page type
  106. page offset 00000000, page type
  107. page offset 00000000, page type
  108. page offset 00000000, page type
  109. page offset 00000000, page type
  110. page offset 00000000, page type
  111. page offset 00000000, page type
  112. page offset 00000000, page type
  113. page offset 00000000, page type
  114. page offset 00000000, page type
  115. page offset 00000000, page type
  116. page offset 00000000, page type
  117. page offset 00000000, page type
  118. page offset 00000000, page type
  119. page offset 00000000, page type
  120. page offset 00000000, page type
  121. page offset 00000000, page type
  122. page offset 00000000, page type
  123. page offset 00000000, page type
  124. page offset 00000000, page type
  125. page offset 00000000, page type
  126. page offset 00000000, page type
  127. page offset 00000000, page type
  128. page offset 00000000, page type
  129. page offset 00000000, page type
  130. Total number of page: 128:
  131. Freshly Allocated Page: 91
  132. Insert Buffer Bitmap: 1
  133. File Space Header: 1
  134. B-tree Node: 34
  135. File Segment inode: 1

四、页

同大多数数据库一样,InnoDB有页(page)的概念(也可以称为块),页是InnoDB磁盘管理的最小单位。与Oracle类似的是,Microsoft SQL Server数据库默认每页大小为8KB,不同于InnoDB页的默认大小(16KB);innodb 1.2.X版本开始,可以通过参数innodb_page_size参数将页的大小设置为4K、8K、16K。若设置完成,则所有表中也的大小都是innodb_page_size,不可以对其再次进行修改;除非通过mysqldump导入导出的操作来产生新的库;

Innodb存储引擎中,常见的页类型有:
(1)数据页(B-tree Node)。
(2)Undo页(Undo Log Page)。
(3)系统页(System Page)。
(4)事务数据页(Transaction system Page)。
(5)插入缓冲位图页(Insert Buffer Bitmap)。
(6)插入缓冲空闲列表页(Insert Buffer Free List)。
(7)未压缩的二进制大对象页(Uncompressed BLOB Page)。
(8)压缩的二进制大对象页(Compressed BLOB Page)。

MYSQL Innodb逻辑存储结构的更多相关文章

  1. MySQL InnoDB 逻辑存储结构

    MySQL InnoDB 逻辑存储结构 从InnoDB存储引擎的逻辑结构看,所有数据都被逻辑地存放在一个空间内,称为表空间,而表空间由段(sengment).区(extent).页(page)组成.p ...

  2. InnoDB 逻辑存储结构

    本文同时发表在https://github.com/zhangyachen/zhangyachen.github.io/issues/80 如果创建表时没有显示的定义主键,mysql会按如下方式创建主 ...

  3. InnoDB逻辑存储结构

    从InnoDB存储引擎的逻辑存储结构看,所有数据都被逻辑地存放在一个空间中,称之为表空间(tablespace).表空间又由段(segment).区(extent).页(page)组成.页在一些文档中 ...

  4. MySQL InnoDB的存储结构总结

    从物理意义上来讲,InnoDB表由共享表空间.日志文件组(redo文件组).表结构定义文件组成.若将innodb_file_per_table设置为on,则系统将为每一个表单独的生成一个table_n ...

  5. InnoDB存储引擎介绍-(5) Innodb逻辑存储结构

    如果创建表时没有显示的定义主键,mysql会按如下方式创建主键: 首先判断表中是否有非空的唯一索引,如果有,则该列为主键. 如果不符合上述条件,存储引擎会自动创建一个6字节大小的指针. 当表中有多个非 ...

  6. InnoDB存储引擎表的逻辑存储结构

    1.索引组织表:     在InnoDB存储引擎中,表都是依照主键顺序组织存放的.这样的存储方式的表称为索引组织表,在innodb存储引擎表中,每张表都有主键.假设创建的时候没有显式定义主键,则Inn ...

  7. InnoDB的表类型,逻辑存储结构,物理存储结构

    表类型 对比Oracle支持的各种表类型,InnoDB存储引擎表更像是Oracle中的索引组织表(index organized table).在InnoDB存储引擎表中,每张表都有个主键,如果在创建 ...

  8. Mysql+innodb数据存储逻辑

    Mysql+innodb数据存储逻辑. 表空间由段,区,页组成 ibdata1:共享表空间.即所有的数据都存放在这个表空间内.如果用户启用了innodb_file_per_table,则每张表内的数据 ...

  9. Innodb页面存储结构-2

    上一篇<Innodb页面存储结构-1>介绍了Innodb页面存储的总体结构,本文会介绍页面的详细内容,主要包括页头.页尾和记录的详细格式. 学习数据结构时都说程序等于数据结构+算法,而在i ...

随机推荐

  1. How to mount EFI on macOS

    mount -t msdos /dev/disk0s1 /volumes/efi

  2. codeforces545C

    Woodcutters CodeForces - 545C Little Susie listens to fairy tales before bed every day. Today's fair ...

  3. 学习Linux系统的态度及技巧

    Linux作为一种简单快捷的操作系统,现在被广泛的应用.也适合越来越多的计算机爱好者学习和使用.但是对于Linux很多人可能认为很难,觉得它很神秘,从而对其避而远之,但事实真的是这样么?linux真的 ...

  4. a标签实现锚点功能

    a标签实现锚点功能 <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  5. linux-shell系列4-init

    #!/bin/bash # 过滤出MAC地址MAC=`ifconfig |awk '{print $5}'|sed -n '1p;1q'` # 过滤网卡名字NET_NAME=`ifconfig |aw ...

  6. Git——取消merge状态

    MERGING状态 取消MERGING 查看更新历史 $ git reflog 恢复之前状态 $ git reset --hard 06a5578

  7. POJ3013-Big Christmas Tree-最短路

    题意:给出一个图,每个节点都有权值,每条边也有费用.要求建立一颗树,使总花费最小.树上每连一条边的花费定义为孩子节点权值和×此边费用. 做法:分析可知,最终的答案为所有节点的权值×到根节点的距离.可以 ...

  8. 大学实验3指导:利用单链表实现A-B

    实验目的:深入理解单链表的建立及操作 实验内容: 1.建立单链表A与B 2.实现主要的函数,查找.插入.删除等 3.实现操作A-B 步骤1:包含必要的函数库,对结构体LNode中的抽象数据类型Elem ...

  9. [ZJOI2009]函数 题解

    题目链接:[ZJOI2009]函数 对于$n=1$的情况,直接输出$1$ 对于$n>1$的情况,由于我们可以将图上下反转,所以第$k$层的情况可以被转成第$n-k+1$层 规律自己打个表可以推出 ...

  10. synchronized 关键字解析

    synchronized 关键字解析 同步锁依赖于对象,每个对象都有一个同步锁. 现有一成员变量 Test,当线程 A 调用 Test 的 synchronized 方法,线程 A 获得 Test 的 ...