MYSQL ERROR 1146 Table doesnt exist 解析
原創轉載請註明出處
原始碼版本 5.7.14
在MYSQL使用innodb的時候我們有時候會看到如下報錯:
ERROR 1146 (42S02): Table 'test.test1bak' doesn't exist
首先總結下原因:
- 缺少frm檔案
- innodb資料字典不包含這個表
我們重點討論情況2,因為情況1是顯而易見的。
?在使用innodb儲存引擎的時候某些時候我們show tables能夠看到這個表,但是如果進行任何操作會報錯如下:
mysql> show tables; | test1bak | mysql> desc test1bak ; ERROR 1146 (42S02): Table 'test.test1bak' doesn't exist
也許你會說我明明能夠看到這個表啊,為什麼訪問還會報錯呢?其實要清楚innodb有自己的資料字典,只要有frm 檔案存在show tables就能看到,但是最終是否能夠正常開啟表結構在innodb中還依賴於innodb的資料字典,主要的包含:
- INNODB_SYS_columns
- INNODB_SYS_FIELDS
- INNODB_SYS_TABLES
- INNODB_SYS_INDEXES
如果報錯出現我們需要首先檢視的是INNODB_SYS_TABLES是否包含了這個表的資訊。也許在這些資料字典中也許某些列並顯示並不是那麼明確,比如
mysql> select * from information_schema.innodb_sys_tables where name='test/kkkkm1'; +----------+-------------+------+--------+-------+-------------+------------+---------------+------------+ | TABLE_ID | NAME | FLAG | N_COLS | SPACE | FILE_FORMAT | ROW_FORMAT | ZIP_PAGE_SIZE | SPACE_TYPE | +----------+-------------+------+--------+-------+-------------+------------+---------------+------------+ | 374 | test/kkkkm1 | 33 | 6 | 540 | Barracuda | Dynamic | 0 | Single | +----------+-------------+------+--------+-------+-------------+------------+---------------+------------+
比如這裡的FLAG列為33,他實際上是一個點陣圖表示方式,分別表示如下資訊:
/* Table and tablespace flags are generally not used for the Antelope file format except for the low order bit, which is used differently depending on where the flags are stored. ==================== Low order flags bit ========================= | REDUNDANT | COMPACT | COMPRESSED and DYNAMIC SYS_TABLES.TYPE | 1 | 1 | 1 dict_table_t::flags | 0 | 1 | 1 FSP_SPACE_FLAGS | 0 | 0 | 1 fil_space_t::flags | 0 | 0 | 1 /** Width of the COMPACT flag */ #define DICT_TF_WIDTH_COMPACT 1 /** Width of the ZIP_SSIZE flag */ #define DICT_TF_WIDTH_ZIP_SSIZE 4 /** Width of the ATOMIC_BLOBS flag. The Antelope file formats broke up BLOB and TEXT fields, storing the first 768 bytes in the clustered index. Barracuda row formats store the whole blob or text field off-page atomically. Secondary indexes are created from this external data using row_ext_t to cache the BLOB prefixes. */ #define DICT_TF_WIDTH_ATOMIC_BLOBS 1 /** If a table is created with the MYSQL option DATA DIRECTORY and innodb-file-per-table, an older engine will not be able to find that table. This flag prevents older engines from attempting to open the table and allows InnoDB to update_create_info() accordingly. */ #define DICT_TF_WIDTH_DATA_DIR 1 /** Width of the SHARED tablespace flag. It is used to identify tables that exist inside a shared general tablespace. If a table is created with the TABLESPACE=tsname option, an older engine will not be able to find that table. This flag prevents older engines from attempting to open the table and allows InnoDB to quickly find the tablespace. */ #define DICT_TF_WIDTH_SHARED_SPACE 1
接下來我們分析一下為什麼是FLAG是33如下:
33的二進位制為00100001從低位開始 1:從原始碼註釋來看本位COMPACT/COMPRESSED/DYNAMIC均為1 0000: ZIP_SSIZE flag 這四位用於支援壓縮功能如COMPRESSED 1:ATOMIC_BLOBS flag 這一位是COMPACT和DYNAMIC主要區別所在,請看原始碼註釋 0:DATA DIRECTORY and innodb-file-per-table flag為了支援DATA DIRECTORY語法 0:SHARED tablespace flag為了支援TABLESPACE語法
然後我們測試一下:
如果我們建立如下的表: CREATE TABLE t2 (c1 INT PRIMARY KEY) TABLESPACE = innodb_file_per_table DATA DIRECTORY = '/root/mysql5.7.14/percona-server-5.7.14-7/mysql-test/var/mysqld.1'; 其type為97二進位制為 01100001:使用DATA DIRECTORY建立使用ATOMIC_BLOBS且無壓縮則DYNAMIC格式 詳見:15.5.5 Creating a File-Per-Table Tablespace Outside the Data Directory 如果我們建立如下的表: CREATE TABLESPACE tt1 ADD DATAFILE '/root/mysql5.7.14/tt1.ibd'; CREATE TABLE tsh (c1 INT ) TABLESPACE tt1 ROW_FORMAT=COMPACT ; 其type為129二進位制為 10000001:使用TABLESPACE語法建立不使用ATOMIC_BLOBS且無壓縮則為COMPACT格式 詳見:15.5.9 InnoDB General Tablespaces
我們可以看到使用8位一個位元組而已就可以表示出大量的資訊,這也是點陣圖的優勢,其他比如 MTYPE/PRTYPE也是這種表示方式
接下來我們回到主題,需要看看這個錯到底是哪裡報錯來的?進行trace後如下,我們來看看主要部分:
注意這裡的trace是mysql debug版本下檢視函式呼叫的主要方法參考官方文件26.5.1.2 Creating Trace Files502 T@2: | | | | | | | | | | | >ha_innobase::open_dict_table 503 T@2: | | | | | | | | | | | | >dict_table_open_on_name 504 T@2: | | | | | | | | | | | | | dict_table_open_on_name: table: 'test/test1bak' 505 T@2: | | | | | | | | | | | | | >dict_table_check_if_in_cache_low 506 T@2: | | | | | | | | | | | | | | dict_table_check_if_in_cache_low: table: 'test/test1bak' 507 T@2: | | | | | | | | | | | | | <dict_table_check_if_in_cache_low 125 508 T@2: | | | | | | | | | | | | | >dict_load_table 509 T@2: | | | | | | | | | | | | | | dict_load_table: loading table: 'test/test1bak' 510 T@2: | | | | | | | | | | | | | | >dict_table_check_if_in_cache_low 511 T@2: | | | | | | | | | | | | | | | dict_table_check_if_in_cache_low: table: 'test/test1bak' 512 T@2: | | | | | | | | | | | | | | <dict_table_check_if_in_cache_low 125 513 T@2: | | | | | | | | | | | | | | >dict_load_table_one 514 T@2: | | | | | | | | | | | | | | | dict_load_table_one: table: test/test1bak 515 T@2: | | | | | | | | | | | | | | | >dict_table_check_if_in_cache_low 516 T@2: | | | | | | | | | | | | | | | | dict_table_check_if_in_cache_low: table: 'SYS_TABLES' 517 T@2: | | | | | | | | | | | | | | | <dict_table_check_if_in_cache_low 125 518 T@2: | | | | | | | | | | | | | | | >btr_cur_search_to_nth_level 519 T@2: | | | | | | | | | | | | | | | <btr_cur_search_to_nth_level 2005 520 T@2: | | | | | | | | | | | | | | <dict_load_table_one 3084 521 T@2: | | | | | | | | | | | | | <dict_load_table 2882 522 T@2: | | | | | | | | | | | | <dict_table_open_on_name 1292 523 T@2: | | | | | | | | | | | <ha_innobase::open_dict_table 6676 524 T@2: | | | | | | | | | | | >sql_print_warning 525 T@2: | | | | | | | | | | | | >error_log_print 526 T@2: | | | | | | | | | | | | | >print_buffer_to_file 527 T@2: | | | | | | | | | | | | | | enter: buffer: InnoDB: Cannot open table test/test1bak from the internal data dictionary of InnoDB though the .frm file for the table exists. Please refer to http://dev.mysql.com/doc/refman/5.7/en/innodb-troubleshooting.html for how to resolve the issue. 528 T@2: | | | | | | | | | | | | | <print_buffer_to_file 2332 529 T@2: | | | | | | | | | | | | <error_log_print 2357 530 T@2: | | | | | | | | | | | <sql_print_warning 2384其實大概步驟就是
-
Checks if a table is in the dictionary cache
根據dict_sys->table_hash尋找 -
Loads a table definition and also all its index definitions.
透過掃描字典的B+樹進行載入 - 如果不能找到則報錯
這樣也就解釋了為什麼show tables能夠看到但是select卻報錯Table doesn't exist ,而從原理上講show tables只是檢視了frm檔案。
另外這裡也提一個案列,曾經有一個朋友問我他將整個庫目錄都複製了,但是表能看到但是一操作就報Table doesn't exist,顯然他沒有複製ibdata1,資料字典的引導資訊都存在這裡面檔案的第7個page中,其b+樹也是存在其中,用原始碼解釋一下:
/**********************************************************************//** Gets a pointer to the dictionary header and x-latches its page. @return pointer to the dictionary header, page x-latched */ dict_hdr_t* dict_hdr_get( /*=========*/ mtr_t* mtr) /*!< in: mtr */ { buf_block_t* block; dict_hdr_t* header; block = buf_page_get(page_id_t(DICT_HDR_SPACE, DICT_HDR_PAGE_NO), univ_page_size, RW_X_LATCH, mtr); header = DICT_HDR + buf_block_get_frame(block); buf_block_dbg_add_level(block, SYNC_DICT_HEADER); return(header); }
注意這裡的 DICT_HDR_SPACE, DICT_HDR_PAGE_NO分別是宏定義
/* Space id and page no where the dictionary header resides */ #define DICT_HDR_SPACE 0 /* the SYSTEM tablespace */ #define DICT_HDR_PAGE_NO FSP_DICT_HDR_PAGE_NO #define FSP_DICT_HDR_PAGE_NO 7 /*!< data dictionary header page, in tablespace 0 */
space 0就是ibdata1的space_no,7當然就是引導塊,這哥們連ibdata1都沒複製,當然innodb資料字典自然不包含這些表了。其實也是上面描述的原理 。
?那麼正確的複製的方式一定是停機後,整個資料目錄進行複製,而不是僅僅複製需要的庫的目錄,否則innodb資料字典是不能正常載入的。
/*--------------------------------------*/ #define FSP_XDES_OFFSET 0 /* !< extent descriptor */ #define FSP_IBUF_BITMAP_OFFSET 1 /* !< insert buffer bitmap */ /* The ibuf bitmap pages are the ones whose page number is the number above plus a multiple of XDES_DESCRIBED_PER_PAGE */ #define FSP_FIRST_INODE_PAGE_NO 2 /*!< in every tablespace */ /* The following pages exist in the system tablespace (space 0). */ #define FSP_IBUF_HEADER_PAGE_NO 3 /*!< insert buffer header page, in tablespace 0 */ #define FSP_IBUF_TREE_ROOT_PAGE_NO 4 /*!< insert buffer B-tree root page in tablespace 0 */ /* The ibuf tree root page number in tablespace 0; its fseg inode is on the page number FSP_FIRST_INODE_PAGE_NO */ #define FSP_TRX_SYS_PAGE_NO 5 /*!< transaction system header, in tablespace 0 */ #define FSP_FIRST_RSEG_PAGE_NO 6 /*!< first rollback segment page, in tablespace 0 */ #define FSP_DICT_HDR_PAGE_NO 7 /*!< data dictionary header page, in tablespace 0 */ ****/*--------------------------------------*/****
作者微信:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2144472/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- ERROR 1146 (42S02): Table 'mysql.slow_log' doesn't existErrorMySql
- MySQL查詢報錯:ERROR 1146 (42S02): Table 'craw.sitePageConfig' doesn't existMySqlError
- lower_case_table_names引數設定解決Error Code: 1146. Table doesn't exist?Error
- SNMP TABLE ERROR : Requested table is empty or does not existError
- [BUG反饋]子查詢報錯,Base table or view not found: 1146 Table 'onethink.(' doesn't existView
- 'mysql.column_stats' doesn't exist and Table 'mysql.index_stats' doesn't existMySqlIndex
- MySQL 啟動報錯 Table 'mysql.plugin' doesn't existMySqlPlugin
- Fatal error: Can't open and lock privilege tables: Table 'mysql.user' doesn't exist解決辦法ErrorMySql
- from v * ERROR at line 1: ORA-00942: table or view does not existErrorView
- 【MySQL】5.6.x InnoDB Error Table mysql.innodb_table_stats not foundMySqlError
- MIRO Error:Table T169V: entry G180 does not existError
- [ERROR] Can't open the mysql.plugin tableErrorMySqlPlugin
- MySQL 5.6執行DDL報錯ERROR 1050 (42S01): Table 'sms/#sql-ib752' already existMySqlError
- MIGO Error:Check table 169P: entry G180 does not existGoError
- MySQL報錯Table 'plugin' is read only [ERROR] Can't open the mysql.plugin table.MySqlPluginError
- Setup had an error Error: At least one of these paths should existErrorAST
- 易優CMS【錯誤程式碼】 SQLSTATE【42S02】:Base table or view not found:1146 Table‘111.ey_admin_theme‘doesn‘t exist-eyoucmsSQLView
- ORA-00942: table or view does not existView
- PSQLexception: ERROR : type "signed" does not existSQLExceptionError
- MySQL 5.5原始碼安裝時啟動資料庫報錯"Table 'mysql.user' doesn't exist??"MySql原始碼資料庫
- PL/SQL: ORA-00942: table or view does not existSQLView
- MySQL DROP TABLE刪除表報錯'ERROR 1051 (42S02): Unknown table'MySqlError
- Linux環境下MySQL報Table 'xxx' doesn't exist錯誤解決方法LinuxMySql
- MySQL ERROR 1031 (HY000) at line 33: Table storage engine forMySqlError
- HPUX Error 23 File table overflowUXError
- 【MySQL】mysql optimize tableMySql
- MySQL 5.5 報錯"ERROR 1075 (42000): Incorrect table definition"MySqlError
- 【MySQL】ERROR 1005 (HY000): Can't create table' (errno: 150)MySqlError
- yii2接入pgSQL(查詢不到表The table does not exist: {{%user}})SQL
- imp 時出現在ORA-00942: table or view does not existView
- ERROR 1548 (HY000): Cannot load from mysql.proc. The table is probably corruptedErrorMySql
- job呼叫過程報錯 ORA-00942: table or view does not existView
- 解析MYSQL BINLOG 二進位制格式(4)--TABLE_MAP_EVENTMySql
- MySQL table into a golang strucMySqlGolang
- create table of mysql databaseMySqlDatabase
- GTID環境中手動修復主從故障一例(Error 1146)Error
- 【MySQL】重放binlog故障一則 ERROR 1050 (42S01) : Table '' already existsMySqlError
- alter table engine=memory ERROR 1114Error