±à¼ÍƼö: |
±¾ÎÄÀ´×ÔÓÚcsdn£¬±¾ÎĽéÉÜÁËInnoDB±í¿Õ¼äÎļþÖеÄÖ÷Òª×éÖ¯½á¹¹¶Î£¬Çø/´Ø£¬Ò³µÈÏà¹Ø¸ÅÄÒÔ¼°innodbµÄÎļþ¹ÜÀí·½Ê½£¬Ï£Íû¶ÔÄúÄÜÓÐËù°ïÖú¡£ |
|
Ò» Ðò£º
ÔÚÕûÀíInnoDB´æ´¢ÒýÇæµÄË÷ÒýµÄʱºò£¬·¢ÏÖB+Ê÷ÊÇÀë²»¿ªÒ³ÃæpageµÄ¡£ËùÒÔÏÈÕûÀíInnoDBµÄÊý¾Ý´æ´¢½á¹¹¡£
¹Ø¼ü´Ê£ºPages, Extents, Segments, and Tablespaces
ÈçºÎ´æ´¢±í
MySQL ʹÓà InnoDB ´æ´¢±íʱ£¬»á½«±íµÄ¶¨ÒåºÍÊý¾ÝË÷ÒýµÈÐÅÏ¢·Ö¿ª´æ´¢£¬ÆäÖÐǰÕß´æ´¢ÔÚ .frm
ÎļþÖУ¬ºóÕß´æ´¢ÔÚ .ibd ÎļþÖУ¬ÕâÒ»½Ú¾Í»á¶ÔÕâÁ½ÖÖ²»Í¬µÄÎļþ·Ö±ð½øÐнéÉÜ¡£
.frm
ÎÞÂÛÔÚ MySQL ÖÐÑ¡ÔñÁËÄĸö´æ´¢ÒýÇæ£¬ËùÓÐµÄ MySQL ±í¶¼»áÔÚÓ²ÅÌÉÏ´´½¨Ò»¸ö .frm ÎļþÓÃÀ´ÃèÊö±íµÄ¸ñʽ»òÕß˵¶¨Ò壻
.frm ÎļþµÄ¸ñʽÔÚ²»Í¬µÄƽ̨É϶¼ÊÇÏàͬµÄ¡£
.ibd Îļþ
InnoDB ÖÐÓÃÓÚ´æ´¢Êý¾ÝµÄÎļþ×ܹ²ÓÐÁ½¸ö²¿·Ö£¬Ò»ÊÇϵͳ±í¿Õ¼äÎļþ£¬°üÀ¨ ibdata1¡¢ ibdata2
µÈÎļþ£¬ÆäÖд洢ÁË InnoDB ϵͳÐÅÏ¢ºÍÓû§Êý¾Ý¿â±íÊý¾ÝºÍË÷Òý£¬ÊÇËùÓÐ±í¹«Óõġ£
µ±´ò¿ª innodb_file_per_table Ñ¡Ïîʱ£¬ .ibd Îļþ¾ÍÊÇÿһ¸ö±í¶ÀÓеıí¿Õ¼ä£¬Îļþ´æ´¢Á˵±Ç°±íµÄÊý¾ÝºÍÏà¹ØµÄË÷ÒýÊý¾Ý¡£
±í¿Õ¼ä
innodb´æ´¢ÒýÇæÔÚ´æ´¢Éè¼ÆÉÏÄ£·ÂÁËOracleµÄ´æ´¢½á¹¹£¬ÆäÊý¾ÝÊǰ´ÕÕ±í¿Õ¼ä½øÐйÜÀíµÄ¡£Ð½¨Ò»¸öÊý¾Ý¿âʱ£¬innodb´æ´¢ÒýÇæ»á³õʼ»¯Ò»¸öÃûΪibdata1
µÄ±í¿Õ¼äÎļþ£¬Ä¬ÈÏÇé¿öÏ£¬Õâ¸öÎļþ»á´æ´¢ËùÓбíµÄÊý¾Ý£¬ÒÔ¼°ÎÒÃÇËùÊìÖªµ«¿´²»µ½µÄϵͳ±ísys_tables¡¢sys_columns¡¢sys_indexes
¡¢sys_fieldsµÈ¡£´ËÍ⣬»¹»á´æ´¢ÓÃÀ´±£Ö¤Êý¾ÝÍêÕûÐԵĻعö¶ÎÊý¾Ý£¬µ±È»Õⲿ·ÖÊý¾ÝÔÚа汾µÄMySQLÖУ¬ÒѾ¿ÉÒÔͨ¹ý²ÎÊýÀ´ÉèÖûعö¶ÎµÄ´æ´¢Î»ÖÃÁË£»
¿´Ï¹ÙÍøµÄ½éÉÜ£º
A data file that can hold data for one or more InnoDB
tables and associated indexes.
The system tablespace contains the InnoDB data dictionary,
and prior to MySQL 5.6 holds all other InnoDB tables
by default.
The innodb_file_per_table option, enabled by default
in MySQL 5.6 and higher, allows tables to be created
in their own tablespaces. File-per-table tablespaces
support features such as efficient storage of off-page
columns, table compression, and transportable tablespaces.
See Section 14.7.4, ¡°InnoDB File-Per-Table Tablespaces¡±
for details.
innodb´æ´¢ÒýÇæµÄÉè¼ÆºÜÁé»î£¬¿ÉÒÔͨ¹ý²ÎÊýinnodb_file_per_tableÀ´ÉèÖã¬Ê¹µÃÿһ¸ö±í¶¼¶ÔÓ¦Ò»¸ö×Ô¼ºµÄ¶ÀÁ¢±í¿Õ¼äÎļþ£¬¶ø²»ÊÇ´æ´¢µ½¹«¹²µÄibdata1ÎļþÖС£¶ÀÁ¢µÄ±í¿Õ¼äÎļþÖ®´æ´¢¶ÔÓ¦±íµÄB+Ê÷Êý¾Ý¡¢Ë÷ÒýºÍ²åÈ뻺³åµÈÐÅÏ¢£¬ÆäÓàÐÅÏ¢»¹ÊÇ´æ´¢ÔÚĬÈϱí¿Õ¼äÖС£
Õâ¸öÎļþËù´æ´¢µÄÄÚÈÝÖ÷Òª¾ÍÊÇB+Ê÷£¨Ë÷Òý£©£¬Ò»¸ö±í¿ÉÒÔÓжà¸öË÷Òý£¬Ò²¾ÍÊÇÔÚÒ»¸öÎļþÖУ¬¿ÉÒÔ´æ´¢¶à¸öË÷Òý£¬¶øÈç¹ûÒ»¸ö±íûÓÐË÷ÒýµÄ»°£¬ÓÃÀ´´æ´¢Êý¾ÝµÄ±»³ÆÎª¾Û´ØË÷Òý£¬Ò²¾ÍÊÇ˵ÕâÒ²ÊÇÒ»¸öË÷Òý¡£×îÖյĽáÂÛÊÇ£¬ibdÎļþ´æ´¢µÄ¾ÍÊÇÒ»¸ö±íµÄËùÓÐË÷ÒýÊý¾Ý¡£
Ë÷ÒýÎļþÓжΣ¨segment£©,´Ø£¨extends£©£¨ÓеÄÎÄÕ·ÒëÎªÇø£©£¬Ò³Ã棨page£©×é³É¡£
¹ØÓÚÐмǼ¸ñʽ£¬µ¥¶ÀÕûÀíһƪ¡£
¶þ ¶Î£¨segment£©
¶ÎÊDZí¿Õ¼äÎļþÖеÄÖ÷Òª×éÖ¯½á¹¹£¬ËüÊÇÒ»¸öÂß¼¸ÅÄÓÃÀ´¹ÜÀíÎïÀíÎļþ£¬Êǹ¹³ÉË÷Òý¡¢±í¡¢»Ø¹ö¶ÎµÄ»ù±¾ÔªËØ¡£
ÉÏͼÖÐÏÔʾÁ˱í¿Õ¼äÊÇÓɸ÷¸ö¶Î×é³ÉµÄ£¬³£¼ûµÄ¶ÎÓÐÊý¾Ý¶Î¡¢Ë÷Òý¶Î¡¢»Ø¹ö¶ÎµÈ¡£InnoDB´æ´¢ÒýÇæ±íÊÇË÷Òý×éÖ¯µÄ£¨index
organized£©£¬Òò´ËÊý¾Ý¼´Ë÷Òý£¬Ë÷Òý¼´Êý¾Ý¡£ÄÇôÊý¾Ý¶Î¼´ÎªB+Ê÷µÄÒ³½Úµã£¨ÉÏͼµÄleaf node
segment£©£¬Ë÷Òý¶Î¼´ÎªB+Ê÷µÄ·ÇË÷Òý½Úµã£¨ÉÏͼµÄnon-leaf node segment£©¡£
´´½¨Ò»¸öË÷Òý£¨B+Ê÷£©Ê±»áͬʱ´´½¨Á½¸ö¶Î£¬·Ö±ðÊÇÄÚ½Úµã¶ÎºÍÒ¶×ӶΣ¬ÄÚ½Úµã¶ÎÓÃÀ´¹ÜÀí£¨´æ´¢£©B+Ê÷·ÇÒ¶×Ó£¨Ò³Ã棩µÄÊý¾Ý£¬Ò¶×Ó¶ÎÓÃÀ´¹ÜÀí£¨´æ´¢£©B+Ê÷Ò¶×Ó½ÚµãµÄÊý¾Ý£»Ò²¾ÍÊÇ˵£¬ÔÚË÷ÒýÊý¾ÝÁ¿Ò»Ö±Ôö³¤µÄ¹ý³ÌÖУ¬ËùÓÐеĴ洢¿Õ¼äµÄÉêÇ룬¶¼ÊÇ´Ó¡°¶Î¡±Õâ¸ö¸ÅÄîÖÐÉêÇëµÄ¡£
ΪÁ˽éÉÜË÷ÒýΪĿµÄ£¬ËùÒÔ²»Õ¹¿ª½éÉܻعö¶ÎµÈÄÚÈÝ¡£
Èý Çø/´Ø£¨extents£©
¶ÎÊǸöÂß¼¸ÅÄinnodbÒýÈëÁ˴صĸÅÄÔÚ´úÂëÖб»³ÆÎªextent£»
´ØÊÇÓÉ64¸öÁ¬ÐøµÄÒ³×é³ÉµÄ£¬Ã¿¸öÒ³´óСΪ16KB£¬¼´Ã¿¸ö´ØµÄ´óСΪ1MB¡£´ØÊǹ¹³É¶ÎµÄ»ù±¾ÔªËØ£¬Ò»¸ö¶ÎÓÉÈô¸É¸ö´Ø¹¹³É¡£Ò»¸ö´ØÊÇÎïÀíÉÏÁ¬Ðø·ÖÅäµÄÒ»¸ö¶Î¿Õ¼ä£¬Ã¿Ò»¸ö¶ÎÖÁÉÙ»áÓÐÒ»¸ö´Ø£¬ÔÚ´´½¨Ò»¸ö¶Îʱ»á´´½¨Ò»¸öĬÈϵĴء£Èç¹û´æ´¢Êý¾Ýʱ£¬Ò»¸ö´ØÒѾ²»×ãÒÔ·Åϸü¶àµÄÊý¾Ý£¬´ËʱÐèÒª´ÓÕâ¸ö¶ÎÖзÖÅäÒ»¸öеĴØÀ´´æ·ÅеÄÊý¾Ý¡£Ò»¸ö¶ÎËù¹ÜÀíµÄ¿Õ¼ä´óСÊÇÎÞÏ޵ģ¬¿ÉÒÔÒ»Ö±À©Õ¹ÏÂÈ¥£¬µ«ÊÇÀ©Õ¹µÄ×îСµ¥Î»¾ÍÊÇ´Ø¡£
ËÄ Ò³£¨page£©
InnoDBÓÐÒ³£¨page£©µÄ¸ÅÄ¿ÉÒÔÀí½âΪ´ØµÄϸ»¯¡£Ò³ÊÇInnoDB´ÅÅ̹ÜÀíµÄ×îСµ¥Î»¡£
³£¼ûµÄÒ³ÀàÐÍÓУº
Êý¾ÝÒ³£¨B-tree Node£©¡£
UndoÒ³£¨Undo Log Page£©¡£
ϵͳҳ£¨System Page£©¡£
ÊÂÎñÊý¾ÝÒ³£¨Transaction system Page£©¡£
²åÈ뻺³åλͼҳ£¨Insert Buffer Bitmap£©¡£
²åÈ뻺³å¿ÕÏÐÁбíÒ³£¨Insert Buffer Free List£©¡£
δѹËõµÄ¶þ½øÖÆ´ó¶ÔÏóÒ³£¨Uncompressed BLOB Page£©¡£
ѹËõµÄ¶þ½øÖÆ´ó¶ÔÏóÒ³£¨Compressed BLOB Page£©¡£
ÔÚÂß¼ÉÏ£¨Ò³ÃæºÅ¶¼ÊÇ´ÓСµ½´óÁ¬ÐøµÄ£©¼°ÎïÀíÉ϶¼ÊÇÁ¬ÐøµÄ¡£ÔÚÏò±íÖвåÈëÊý¾Ýʱ£¬Èç¹ûÒ»¸öÒ³ÃæÒѾ±»Ð´Í꣬ϵͳ»á´Óµ±Ç°´ØÖзÖÅäÒ»¸öеĿÕÏÐÒ³Ãæ´¦ÀíʹÓã¬Èç¹ûµ±Ç°´ØÖеÄ64¸öÒ³Ãæ¶¼±»·ÖÅäÍ꣬ϵͳ»á´Óµ±Ç°Ò³ÃæËùÔÚ¶ÎÖзÖÅäÒ»¸öеĴأ¬È»ºóÔÙ´ÓÕâ¸ö´ØÖзÖÅäÒ»¸öеÄÒ³ÃæÀ´Ê¹Óã»
¿´Ï¹ÙÍøµÄ½éÉÜ£º
Pages, Extents, Segments, and Tablespaces
Each tablespace consists of database?pages. Every
tablespace in a MySQL instance has the same?page size.
By default, all tablespaces have a page size of 16KB;
you can reduce the page size to 8KB or 4KB by specifying
the?innodb_page_size?option when you create the MySQL
instance. You can also increase the page size to 32KB
or 64KB. For more information, refer to the?innodb_page_sizedocumentation.
The pages are grouped into?extents?of size 1MB for
pages up to 16KB in size (64 consecutive 16KB pages,
or 128 8KB pages, or 256 4KB pages). For a page size
of 32KB, extent size is 2MB. For page size of 64KB,
extent size is 4MB. The?¡°files¡±?inside a tablespace
are called?segments?in?InnoDB. (These segments are
different from the?rollback segment, which actually
contains many tablespace segments.)
When a segment grows inside the tablespace,?InnoDB?allocates
the first 32 pages to it one at a time. After that,?InnoDB?starts
to allocate whole extents to the segment.?InnoDB?can
add up to 4 extents at a time to a large segment to
ensure good sequentiality of data.
Two segments are allocated for each index in?InnoDB.
One is for nonleaf nodes of the?B-tree, the other
is for the leaf nodes. Keeping the leaf nodes contiguous
on disk enables better sequential I/O operations,
because these leaf nodes contain the actual table
data.
Some pages in the tablespace contain bitmaps of other
pages, and therefore a few extents in an?InnoDB?tablespace
cannot be allocated to segments as a whole, but only
as individual pages.
Îå ×éÖ¯½á¹¹
ÕâÀïÔÚ¡¶MySQLÔËάÄڲΡ·ËµµÄ²»ÊÇÌØ±ðϸ£ºÒ»¸ö±í¿Õ¼ä¿ÉÒÔÓжà¸öÎļþ£¬Ã¿¸öÎļþ¶¼Óи÷×ԵıàºÅ£¬´´½¨Ò»¸ö±í¿Õ¼äʱ£¬ÖÁÉÙÓÐÒ»¸öÎļþ£¬Õâ¸öÎļþ±»³ÆÎª¡°0ºÅÎļþ¡±¡£Ò»¸öÎļþÊDZ»ÇиîΪµÈ³¤¡°Ä¬ÈÏ16KB¡±µÄ¿é£¬Õâ¸ö¿éͨ³£±»³ÆÎªÒ³Ã棬ÄÇôÔÚ¡°0ºÅÎļþ¡±µÄµÚÒ»¸öÒ³Ãæ£¨page_noΪ0£©ÖУ¬´æ´¢ÁËÕâ¸ö±í¿Õ¼äÖÐËùÓжδØÒ²¹ÜÀíµÄÈë¿Ú£¬ÄÇôÔÚÕâ¸öÒ³Ãæ´æ´¢µÄÊý¾Ý¾ÍÊÇ16KB£¬µ«Í¨³£»áÓÐÒ³ÃæÍ·ÐÅÏ¢»áÕ¼ÓÃһЩ¿Õ¼ä£¬ÕæÕýµÄ¹ÜÀíÐÅÏ¢Êý¾ÝÊÇ´ÓÒ³ÃæÆ«ÒÆÎªfil_page_data(38)µÄλÖÿªÊ¼µÄ£¬Õâ¸öλÖô洢Á˱í¿Õ¼äµÄÃèÊöÐÅÏ¢£»
ÌÔ±¦µÄmysql¸ø³öÁ˸üÏêϸ£ºÏÈ¿´Õâ¸öͼ£¬Óиö´ó¸Å¸ÅÄÔÙÍùÏ¿´¡£

5.1 FSP_HDR PAGE
Êý¾ÝÎļþµÄµÚÒ»¸öPageÀàÐÍΪFIL_PAGE_TYPE_FSP_HDR£¬ÔÚ´´½¨Ò»¸öеıí¿Õ¼äʱ½øÐгõʼ»¯(fsp_header_init)£¬¸ÃpageͬʱÓÃÓÚ¸ú×ÙËæºóµÄ256¸öExtent(Ô¼256MBÎļþ´óС)µÄ¿Õ¼ä¹ÜÀí£¬ËùÒÔÿ¸ô256MB¾ÍÒª´´½¨Ò»¸öÀàËÆµÄÊý¾ÝÒ³£¬ÀàÐÍΪFIL_PAGE_TYPE_XDES?£¬XDES
Page³ýÁËÎļþÍ·²¿Í⣬ÆäËû¶¼ºÍFSP_HDRÒ³¾ßÓÐÏàͬµÄÊý¾Ý½á¹¹£¬¿ÉÒÔ³ÆÖ®ÎªExtentÃèÊöÒ³£¬Ã¿¸öExtentÕ¼ÓÃ40¸ö×Ö½Ú£¬Ò»¸öXDES
Page×î¶àÃèÊö256¸öExtent¡£
FSP_HDRÒ³µÄÍ·²¿Ê¹ÓÃFSP_HEADER_SIZE¸ö×Ö½ÚÀ´¼Ç¼ÎļþµÄÏà¹ØÐÅÏ¢£¬¾ßÌåµÄ°üÀ¨£º

´Ø»òÕß·ÖÇø£¨extent£©ÊǶεÄ×é³ÉÔªËØ£¬ÔÚÎļþͷʹÓÃFLAGÃèÊöÁË´´½¨±íÐÅÏ¢£¬³ý´ËÖ®ÍâÆäËû²¿·ÖµÄÊý¾Ý½á¹¹ºÍXDES
PAGE¶¼ÊÇÏàͬµÄ£¬Ê¹ÓÃÁ¬ÐøÊý×éµÄ·½Ê½£¬Ã¿¸öXDES PAGE×î¶à´æ´¢256¸öXDES Entry£¬Ã¿¸öEntryÕ¼ÓÃ40¸ö×Ö½Ú£¬ÃèÊö64¸öPage£¨¼´Ò»¸öExtent£©¡£¸ñʽÈçÏ£º

XDES_STATE±íʾ¸ÃExtentµÄËÄÖÖ²»Í¬×´Ì¬£º

ͨ¹ýXDES_STATEÐÅÏ¢£¬ÎÒÃÇÖ»ÐèÒªÒ»¸öFLIST_NODE½Úµã¾Í¿ÉÒÔά»¤Ã¿¸öExtentµÄÐÅÏ¢£¬ÊÇ´¦ÓÚÈ«¾Ö±í¿Õ¼äµÄÁ´±íÉÏ£¬»¹ÊÇij¸öbtree
segmentµÄÁ´±íÉÏ¡£
IBUF BITMAP PAGE Ò²¾ÍÊÇpageÀàÐÍΪFIL_PAGE_IBUF_BITMAP²»Õ¹¿ª£¬´ýµ¥¶ÀÕûÀí¡£ÔÙ¿´¶ÎµÄ¡£
5.2 INODE PAGE
Êý¾ÝÎļþµÄµÚ3¸öpageµÄÀàÐÍΪFIL_PAGE_INODE£¬ÓÃÓÚ¹ÜÀíÊý¾ÝÎļþÖеÄsegement£¬Ã¿¸öË÷ÒýÕ¼ÓÃ2¸ösegment£¬·Ö±ðÓÃÓÚ¹ÜÀíÒ¶×Ó½ÚµãºÍ·ÇÒ¶×ӽڵ㡣ÿ¸öinodeÒ³¿ÉÒÔ´æ´¢FSP_SEG_INODES_PER_PAGE£¨Ä¬ÈÏΪ85£©¸ö¼Ç¼¡£

ÿ¸öInode EntryµÄ½á¹¹ÈçϱíËùʾ£º

¿´µ½ÕâÀÉÏÃæµÄͼӦ¸ÃÊÇÀí½âÁË£¬µ±È»ÊéÉÏ»¹ÊǸøÁËÒ»¸ö¼ò»¯µÄͼ£º

5.3 Îļþά»¤
´ÓÉÏÎÄÎÒÃÇ¿ÉÒÔ¿´µ½£¬InnoDBͨ¹ýInode EntryÀ´¹ÜÀíÿ¸öSegmentÕ¼ÓõÄÊý¾ÝÒ³£¬Ã¿¸ösegment¿ÉÒÔ¿´×öÒ»¸öÎļþҳά»¤µ¥Ôª¡£Inode
EntryËùÔÚµÄinode pageÓпÉÄÜ´æ·ÅÂú£¬Òò´ËÓÖͨ¹ýÍ·Pageά»¤ÁËInode PageÁ´±í¡£
ÔÚibdµÄµÚÒ»¸öPageÖл¹Î¬»¤Á˱í¿Õ¼äÄÚExtentµÄFREE¡¢FREE_FRAG¡¢FULL_FRAGÈý¸öExtentÁ´±í£»¶øÃ¿¸öInode
EntryҲά»¤Á˶ÔÓ¦µÄFREE¡¢NOT_FULL¡¢FULLÈý¸öExtentÁ´±í¡£ÕâЩÁ´±íÖ®¼ä´æÔÚ×Åת»»¹ØÏµ£¬ÒÔ¸ßЧµÄÀûÓÃÊý¾ÝÎļþ¿Õ¼ä¡£×¢ÒâÇø±ð£º±í¿Õ¼äÖеÄÁ´±í¹ÜÀíµÄÊÇÕû¸ö±í¿Õ¼äÖÐËùÓеĴأ¬°üÀ¨Âú´Ø¡¢°ëÂú´Ø¼°¿ÕÏдأ¬¶ø¶ÎµÄiNodeÐÅÏ¢ÖйÜÀíµÄÊÇÊôÓÚ×Ô¼º¶ÎÖеÄÂú´Ø¡¢°ëÂú´Ø¼°¿ÕÏдء£
µ±´´½¨Ò»¸öеÄË÷Òýʱ£¬Êµ¼ÊÉϹ¹½¨Ò»¸öеÄbtree(btr_create)£¬ÏÈΪ·ÇÒ¶×Ó½ÚµãSegment·ÖÅäÒ»¸öinode
entry£¬ÔÙ´´½¨root page£¬²¢½«¸ÃsegmentµÄλÖüǼµ½root pageÖУ¬È»ºóÔÙ·ÖÅäleaf
segmentµÄInode entry£¬²¢¼Ç¼µ½root pageÖС£µ±É¾³ýij¸öË÷Òýºó£¬¸ÃË÷ÒýÕ¼ÓõĿռäÐèÒªÄܱ»ÖØÐÂÀûÓÃÆðÀ´¡£
´´½¨Ò»¸ösegment£º
º¯ÊýÈë¿Ú£ºfseg_create_general£¬ºóÃæÌùһϴúÂ룬Ö÷ÒªÊÇÊéÉϵĽâÊÍ¡£
1.¸ù¾Ý¿Õ¼äidµÃµ½±í¿Õ¼äÍ·ÐÅÏ¢¡£
2. ´ÓµÃµ½µÄ±í¿Õ¼äÍ·ÐÅÏ¢·ÖÅäInode:¾ßÌåʵÏÖΪ¶ÁÈ¡ÎļþÍ·Page²¢¼ÓËø£¨fsp_get_space_header£©£¬È»ºó¿ªÊ¼ÎªÆä·ÖÅäInode
Entry(fsp_alloc_seg_inode)¡£
ΪÁ˹ÜÀíInode Page£¬ÔÚÎļþÍ·´æ´¢ÁËÁ½¸öInode PageÁ´±í£¬Ò»¸öÁ´½ÓÒѾÓÃÂúµÄinode
page£¬Ò»¸öÁ´½ÓÉÐδÓÃÂúµÄinode page¡£Èç¹ûµ±Ç°Inode PageµÄ¿Õ¼äʹÓÃÍêÁË£¬¾ÍÐèÒªÔÙ·ÖÅäÒ»¸öinode
page£¬²¢¼ÓÈëµ½FSP_SEG_INODES_FREEÁ´±íÉÏ(fsp_alloc_seg_inode_page)¡£¶ÔÓÚ¶ÀÁ¢±í¿Õ¼ä£¬Í¨³£Ò»¸öinode
page¾Í×ã¹»ÁË¡£
ÏÂÃæ¿´¾ßÌå²éÕÒinode Page¹ý³Ì£ºÊ×ÏÈÅжÏFSP_SEG_INODES_FREEÁ´±íÊÇ·ñ»¹ÓпÕÏÐÒ³Ãæ£¬Èç¹ûÓУ¬Ôò´ÓÒ³ÃæµÄÊý¾Ý´æ´¢Î»ÖÿªÊ¼É¨Ã裬ûÕÒÒ»¸öInode£¬ÏÈÅжÏÊÇ·ñ¿ÕÏУ¨¿ÕÏбíʾÆä²»¹éÊôÈκÎsegment£¬¼´FSEG_IDÖÃΪ0£©¡£ÕÒµ½Ôò·µ»Ø¡£ÕÒµ½Õâ¸öÇÒÕâ¸öInodeΪÕâ¸öÒ³×îºóÒ»¸öInode.Ôò¸Ãinode
pageÖеļǼÓÃÂúÁË£¬¾Í´ÓFSP_SEG_INODES_FREEÁ´±íÉÏ×ªÒÆµ½FSP_SEG_INODES_FULLÁ´±í¡£Èç¹ûFSP_SEG_INODES_FREEûÓпÕÏеÄInodeÒ³Ãæ£¬ÔòÖØÐ·ÖÅäÒ»¸öinodeÒ³Ãæ£¬·ÖÅäºó°ÑËùÓÐÃèÊö·ûÀïÃæµÄFSEG_IDÖÃΪ0£¬Öظ´ÉÏÃæ¹ý³Ì¡£
3.¸øÐ·ÖÅäµÄInodeÉèÖÃSEG_ID. Õâ¸öIDºÅÒª´Ó±í¿Õ¼äÍ·ÐÅÏ¢µÄFSP_SEG_ID×÷Ϊµ±Ç°segmentµÄseg
idдÈëµ½inode entryÖС£Í¬Ê±¸üÐÂFSP_SEG_IDµÄֵΪID+1£¬×÷ΪÏÂÒ»¸ö¶ÎµÄIDºÅ¡£
4.ÔÚÍê³Éinode entryµÄÌáÈ¡ºó£¬³õʼ»¯Õâ¸öInodeÐÅÏ¢¡£°ÑFSEG_NOT_FULL_N_USEDÖÃΪ0£¬³õʼ»¯FSEG_FREE¡¢FSEG_NOT_FULL£¬FSEG_FULL¡£
5. ´ÓÕâ¸ö¶Î·ÖÅä³öÒ»¸öÒ³Ãæ¡££¨Õâ¿éÂß¼²»Ì«¶®£©
6.·ÖÅäºÃÒ³Ãæºó£¬Í¨¹ý»º´æÕÒµ½¶ÎµÄÊ×Ò³Ãæ£¨Ò³ÃæºÅΪpage+index£©¡£¾Í½«¸Ãinode entryËùÔÚinode
pageµÄλÖü°Ò³ÄÚÆ«ÒÆÁ¿´æ´¢µ½¶ÎÊ×Ò³£¬10¸ö×Ö½ÚµÄinodeÐÅÏ¢°üÀ¨£º

ÖÁ´Ë¶Î¾Í·ÖÅäÍê³ÉÁË£¬ÒÔºóÈç¹ûÐèÒªÔÚÕâ¸ö¶ÎÖзÖÅä¿Õ¼ä£¬Ö»ÐèÒªÕÒµ½ÆäÊ×Ò³£¬È»ºó¸ù¾Ý¶ÔÓ¦µÄInode·ÖÅä¿Õ¼ä¡£
Creates a new
segment.
@return the block where the segment header is
placed, x-latched, NULL
if could not create segment because of lack of
space */
UNIV_INTERN
buf_block_t*
fseg_create_general(
/*================*/
ulint space, /*!< in: space id */
ulint page, /*!< in: page where the segment
header is placed: if
this is != 0, the page must belong to another
segment,
if this is 0, a new page will be allocated and
it
will belong to the created segment */
ulint byte_offset, /*!< in: byte offset of
the created segment header
on the page */
ibool has_done_reservation, /*!< in: TRUE if
the caller has already
done the reservation for the pages with
fsp_reserve_free_extents (at least 2 extents:
one for
the inode and the other for the segment) then
there is
no need to do the check for this individual
operation */
mtr_t* mtr) /*!< in: mtr */
{
ulint flags;
ulint zip_size;
fsp_header_t* space_header;
fseg_inode_t* inode; //typedef byte fseg_inode_t;
ib_id_t seg_id;
buf_block_t* block = 0; /* remove warning */
fseg_header_t* header = 0; /* remove warning */
rw_lock_t* latch;
ibool success;
ulint n_reserved;
ulint i;
ut_ad(mtr);
ut_ad(byte_offset + FSEG_HEADER_SIZE <=
UNIV_PAGE_SIZE - FIL_PAGE_DATA_END);
latch = fil_space_get_latch(space, &flags);
zip_size = dict_table_flags_to_zip_size(flags);
if (page != 0) {
block = buf_page_get(space, zip_size, page, RW_X_LATCH,
mtr);
header = byte_offset + buf_block_get_frame(block);
}
ut_ad(!mutex_own(&kernel_mutex)
|| mtr_memo_contains(mtr, latch, MTR_MEMO_X_LOCK));
mtr_x_lock(latch, mtr);
if (rw_lock_get_x_lock_count(latch) == 1) {
/* This thread did not own the latch before this
call: free
excess pages from the insert buffer free list
*/
if (space == IBUF_SPACE_ID) {
ibuf_free_excess_pages();
}
}
if (!has_done_reservation) {
success = fsp_reserve_free_extents(&n_reserved,
space, 2,
FSP_NORMAL, mtr);
if (!success) {
return(NULL);
}
}
space_header = fsp_get_space_header (space, zip_size,
mtr);//Ïê¼û
inode = fsp_alloc_seg_inode(space_header, mtr);
//ÉêÇëinode entry Ïê¼û if (inode == NULL) {
goto funct_exit;
}
/* Read the next segment id from space header
and increment the
value in space header */
seg_id = mach_read_from_8(space_header + FSP_SEG_ID);
//ÉèÖÃÏÂÒ»ÏÂseg id
mlog_write_ull(space_header + FSP_SEG_ID, seg_id
+ 1, mtr);
/**
*#define FSEG_ID 0
*#define FSEG_NOT_FULL_N_USED 8
*#define FSEG_FREE 12
*#define FSEG_NOT_FULL (12 + FLST_BASE_NODE_SIZE)
*#define FLST_BASE_NODE_SIZE (4 + 2 * FIL_ADDR_SIZE)
*#define FIL_ADDR_SIZE 6
*
*#define FSEG_FULL (12 + 2 * FLST_BASE_NODE_SIZE)
*
*/
mlog_write_ull(inode + FSEG_ID, seg_id, mtr);
mlog_write_ulint(inode + FSEG_NOT_FULL_N_USED,
0, MLOG_4BYTES, mtr);
flst_init(inode + FSEG_FREE, mtr); //³õʼ»¯inodeÖеÄseg
list Ïê¼û
flst_init(inode + FSEG_NOT_FULL, mtr);
flst_init(inode + FSEG_FULL, mtr);
mlog_write_ulint(inode + FSEG_MAGIC_N, FSEG_MAGIC_N_VALUE,
MLOG_4BYTES, mtr);
//#define FSEG_FRAG_ARR_N_SLOTS (FSP_EXTENT_SIZE
/ 2) 64/2=32 for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS;
i++) {
fseg_set_nth_frag_page_no(inode, i, FIL_NULL,
mtr); //ÉèÖÃfrag Ë鯬 Ïê¼û
}
if (page == 0) {
block = fseg_alloc_free_page_low(space, zip_size,
inode, 0, FSP_UP, mtr, mtr);
if (block == NULL) {
fsp_free_seg_inode(space, zip_size, inode, mtr);
goto funct_exit;
}
ut_ad(rw_lock_get_x_lock_count(&block->lock)
== 1);
header = byte_offset + buf_block_get_frame(block);
mlog_write_ulint(buf_block_get_frame(block) +
FIL_PAGE_TYPE,
FIL_PAGE_TYPE_SYS, MLOG_2BYTES, mtr);
}
//ÉèÖÃfset_headerÐÅÏ¢
mlog_write_ulint(header + FSEG_HDR_OFFSET ,page_offset(inode),
MLOG_2BYTES, mtr);
mlog_write_ulint(header + FSEG_HDR_PAGE_NO,page_get_page_no(page_align(inode)),
MLOG_4BYTES, mtr);
mlog_write_ulint(header + FSEG_HDR_SPACE, space,
MLOG_4BYTES, mtr);
funct_exit:
if (!has_done_reservation) {
fil_space_release_free_extents(space, n_reserved);
}
return(block);
} |
·ÖÅäÊý¾ÝÒ³º¯Êý fsp_alloc_free_page
±í¿Õ¼äExtentµÄ·ÖÅ亯Êýfsp_alloc_free_extent £¬²»ÔÚ´ËÕ¹¿ª¡£
¶ÔÓ¦µÄ»¹ÓÐÊÍ·ÅSegment µ±ÎÒÃÇɾ³ýË÷Òý»òÕß±íʱ£¬ÐèҪɾ³ýbtree£¨btr_free_if_exists£©£¬ÏÈɾ³ý³ýÁËroot½ÚµãÍâµÄÆäËû²¿·Ö(btr_free_but_not_root)£¬ÔÙɾ³ýroot½Úµã(btr_free_root)
ÓÉÓÚÊý¾Ý²Ù×÷¶¼ÐèÒª¼Ç¼redo£¬ÎªÁ˱ÜÃâ²úÉú·Ç³£´óµÄredo log£¬leaf segmentͨ¹ý·´¸´µ÷Óú¯Êýfseg_free_stepÀ´ÊÍ·ÅÆäÕ¼ÓõÄÊý¾ÝÒ³¡£
Áù ´´½¨B+Ë÷Òý
ÉÏÃæÎÒÃÇÒѾ´ó¸ÅÁ˽âÁËinnodbµÄÎļþ¹ÜÀí·½Ê½£¬ºËÐÄÄ¿µÄÊÇΪÁ˹ÜÀíºÃB+Ë÷Òý¡£
ibdÎļþÖÐÕæÕý¹¹½¨ÆðÓû§Êý¾ÝµÄ½á¹¹ÊÇBTREE£¬ÔÚÄã´´½¨Ò»¸ö±íʱ£¬ÒѾ»ùÓÚÏÔʽ»òÒþʽ¶¨ÒåµÄÖ÷¼ü¹¹½¨ÁËÒ»¸öbtree£¬ÆäÒ¶×Ó½ÚµãÉϼǼÁËÐеÄÈ«²¿ÁÐÊý¾Ý£¨¼ÓÉÏÊÂÎñidÁм°»Ø¹ö¶ÎÖ¸ÕëÁУ©£»Èç¹ûÄãÔÚ±íÉÏ´´½¨Á˶þ¼¶Ë÷Òý£¬ÆäÒ¶×Ó½Úµã´æ´¢Á˼üÖµ¼ÓÉϾۼ¯Ë÷Òý¼üÖµ¡£ËùÒÔÊéÉÏÌùÒ»¶Î´´½¨B+Ë÷ÒýµÄ´úÂë¡£ÍøÉÏÕÒÁË5.6.15°æ±¾µÄ¡£Õâ¸öº¯Êý¾ÍÊÇ´´½¨Ò»¸öB+Ê÷£¬Ö»ÊǸÅÄîÉϵ쬻¹Ã»ÓÐÕæÕýµÄÊý¾ÝдÈë¡£
Ïà¹ØÖªÊ¶µã£ºB+Ê÷£¬Ë÷Òý£¬¶Î£¬Çø/´Ø£¨extent£©,Ò³ ÒѾ´®ÆðÀ´ÁË¡£
Creates the root
node for a new index tree.
@return page number of the created root, FIL_NULL
if did not succeed */
UNIV_INTERN
ulint
btr_create(
/*=======*/
ulint type, /*!< in: type of the index */
ulint space, /*!< in: space where created */
ulint zip_size,/*!< in: compressed page size
in bytes
or 0 for uncompressed pages */
index_id_t index_id,/*!< in: index id */
dict_index_t* index, /*!< in: index */
mtr_t* mtr) /*!< in: mini-transaction handle
*/
{
ulint page_no;
buf_block_t* block;
buf_frame_t* frame;
page_t* page;
page_zip_des_t* page_zip;
/* Create the two new segments (one, in the case
of an ibuf tree) for
the index tree; the segment headers are put on
the allocated root page
(for an ibuf tree, not in the root, but on a separate
ibuf header
page) */
if (type & DICT_IBUF) {
/* Allocate first the ibuf header page */
buf_block_t* ibuf_hdr_block = fseg_create(
space, 0,
IBUF_HEADER + IBUF_TREE_SEG_HEADER, mtr);
buf_block_dbg_add_level(
ibuf_hdr_block, SYNC_IBUF_TREE_NODE_NEW);
ut_ad(buf_block_get_page_no(ibuf_hdr_block)
== IBUF_HEADER_PAGE_NO);
/* Allocate then the next page to the segment:
it will be the
tree root page */
block = fseg_alloc_free_page(
buf_block_get_frame(ibuf_hdr_block)
+ IBUF_HEADER + IBUF_TREE_SEG_HEADER,
IBUF_TREE_ROOT_PAGE_NO,
FSP_UP, mtr);
ut_ad(buf_block_get_page_no(block) == IBUF_TREE_ROOT_PAGE_NO);
} else {
#ifdef UNIV_BLOB_DEBUG
if ((type & DICT_CLUSTERED) && !index->blobs)
{
mutex_create(PFS_NOT_INSTRUMENTED, &index->blobs_mutex,
SYNC_ANY_LATCH);
index->blobs = rbt_create(sizeof(btr_blob_dbg_t),
btr_blob_dbg_cmp);
}
#endif /* UNIV_BLOB_DEBUG */
block = fseg_create(space, 0,
PAGE_HEADER + PAGE_BTR_SEG_TOP, mtr);
}
if (block == NULL) {
return(FIL_NULL);
}
page_no = buf_block_get_page_no(block);
frame = buf_block_get_frame(block);
if (type & DICT_IBUF) {
/* It is an insert buffer tree: initialize the
free list */
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO);
flst_init(frame + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
mtr);
} else {
/* It is a non-ibuf tree: create a file segment
for leaf
pages */
buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
if (!fseg_create(space, page_no,
PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr)) {
/* Not enough space for new segment, free root
segment before return. */
btr_free_root(space, zip_size, page_no, mtr);
return(FIL_NULL);
}
/* The fseg create acquires a second latch on
the page,
therefore we must declare it: */
buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
}
/* Create a new index page on the allocated segment
page */
page_zip = buf_block_get_page_zip(block);
if (page_zip) {
page = page_create_zip(block, index, 0, 0, mtr);
} else {
page = page_create(block, mtr,
dict_table_is_comp(index->table));
/* Set the level of the new index page */
btr_page_set_level(page, NULL, 0, mtr);
}
block->check_index_page_at_flush = TRUE;
/* Set the index id of the page */
btr_page_set_index_id(page, page_zip, index_id,
mtr);
/* Set the next node and previous node fields
*/
btr_page_set_next(page, page_zip, FIL_NULL, mtr);
btr_page_set_prev(page, page_zip, FIL_NULL, mtr);
/* We reset the free bits for the page to allow
creation of several
trees in the same mtr, otherwise the latch on
a bitmap page would
prevent it because of the latching order */
if (!(type & DICT_CLUSTERED)) {
ibuf_reset_free_bits(block);
}
/* In the following assertion we test that two
records of maximum
allowed size fit on the root page: this fact is
needed to ensure
correctness of split algorithms */
ut_ad(page_get_max_insert_size(page, 2) > 2
* BTR_PAGE_MAX_REC_SIZE);
return(page_no);
} |
|