1. 程式人生 > >MYSQL ERROR 1146 Table doesnt exist 解析

MYSQL ERROR 1146 Table doesnt exist 解析

在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的資料字典,主要的包含:

  1. INNODB_SYS_columns
  2. INNODB_SYS_FIELDS
  3. INNODB_SYS_TABLES
  4. 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 Files
   502  [email protected]: | | | | | | | | | | | >ha_innobase::open_dict_table
   503  [email protected]: | | | | | | | | | | | | >dict_table_open_on_name
   504  [email protected]: | | | | | | | | | | | | | dict_table_open_on_name: table: 'test/test1bak'
   505  [email protected]: | | | | | | | | | | | | | >dict_table_check_if_in_cache_low
   506  [email protected]: | | | | | | | | | | | | | | dict_table_check_if_in_cache_low: table: 'test/test1bak'
   507  [email protected]: | | | | | | | | | | | | | <dict_table_check_if_in_cache_low 125
   508  [email protected]: | | | | | | | | | | | | | >dict_load_table
   509  [email protected]: | | | | | | | | | | | | | | dict_load_table: loading table: 'test/test1bak'
   510  [email protected]: | | | | | | | | | | | | | | >dict_table_check_if_in_cache_low
   511  [email protected]: | | | | | | | | | | | | | | | dict_table_check_if_in_cache_low: table: 'test/test1bak'
   512  [email protected]: | | | | | | | | | | | | | | <dict_table_check_if_in_cache_low 125
   513  [email protected]: | | | | | | | | | | | | | | >dict_load_table_one
   514  [email protected]: | | | | | | | | | | | | | | | dict_load_table_one: table: test/test1bak
   515  [email protected]: | | | | | | | | | | | | | | | >dict_table_check_if_in_cache_low
   516  [email protected]: | | | | | | | | | | | | | | | | dict_table_check_if_in_cache_low: table: 'SYS_TABLES'
   517  [email protected]: | | | | | | | | | | | | | | | <dict_table_check_if_in_cache_low 125
   518  [email protected]: | | | | | | | | | | | | | | | >btr_cur_search_to_nth_level
   519  [email protected]: | | | | | | | | | | | | | | | <btr_cur_search_to_nth_level 2005
   520  [email protected]: | | | | | | | | | | | | | | <dict_load_table_one 3084
   521  [email protected]: | | | | | | | | | | | | | <dict_load_table 2882
   522  [email protected]: | | | | | | | | | | | | <dict_table_open_on_name 1292
   523  [email protected]: | | | | | | | | | | | <ha_innobase::open_dict_table 6676
   524  [email protected]: | | | | | | | | | | | >sql_print_warning
   525  [email protected]: | | | | | | | | | | | | >error_log_print
   526  [email protected]: | | | | | | | | | | | | | >print_buffer_to_file
   527  [email protected]: | | | | | | | | | | | | | | 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  [email protected]: | | | | | | | | | | | | | <print_buffer_to_file 2332
   529  [email protected]: | | | | | | | | | | | | <error_log_print 2357
   530  [email protected]: | | | | | | | | | | | <sql_print_warning 2384
其實大概步驟就是
  1. Checks if a table is in the dictionary cache
    根據dict_sys->table_hash尋找
  2. Loads a table definition and also all its index definitions.
    通過掃描字典的B+樹進行載入
  3. 如果不能找到則報錯

這樣也就解釋了為什麼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資料字典是不能正常載入的。

最後附帶space 0的部分塊解釋
/*--------------------------------------*/
#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 */
****/*--------------------------------------*/****

相關推薦

MYSQL ERROR 1146 Table doesnt exist 解析

在MYSQL使用innodb的時候我們有時候會看到如下報錯:ERROR 1146 (42S02): Table 'test.test1bak' doesn't exist 首先總結下原因:缺少frm檔案innodb資料字典不包含這個表我們重點討論情況2,因為情況1是顯而易見的。 在使用innodb儲存引擎

mysql 提示表不存在的解決方法error: 1146: Table doesn't exist

直接拷貝資料庫導致提示表不存在的解決方法 電腦重灌系統後把原來的mysql data複製進去後大部分表是可以訪問的,但是有幾個表提示表不存在: error: 1146: Table 'a_content' doesn't exist這種情況就是要把原來mysql安裝目錄data裡的 ibdata1 也要拷

mysql 提示表不存在的解決方法error: 1146: Table doesn't exist

電腦重灌系統後把原來的mysql data複製進去後大部分表是可以訪問的,但是有幾個表提示表不存在: error: 114

selenium WebDriverException: Message: unknown error: DevToolsActivePort file doesnt exist

報錯 環境: CentOS7.5 Python 3.6.5 chromedriver_linux64 2.40 Selenium Google Chrome 67 使用Selenium和Chrome,報如下錯誤: File "/usr/local/anaconda3/lib/python

MySQL ERROR Table 'mysql user' doesn't exist

#檢視錯誤日誌[[email protected] scripts]# tail /var/log/mysqld.logInnoDB: Apply batch completed2014-12-08 11:01:37 15721 [Note] InnoDB: 128 rollback segment

ERROR 1146 (42S02): Table '庫名.表名' doesn't exist

1)首先退出mysql 2)在命令列介面輸入: mysql_upgrade -uroot -p --force 3)然後重啟mysql即可 windows重啟mysql命令是: net stop mysql #關閉mysql net stop mysql

ERROR 1146 (42S02): Table '庫名.表名' doesn't exist

1)首先退出mysql 2)在命令列介面輸入: mysql_upgrade -uroot -p --force 3)然後重啟mysql即可 windows重啟mysql命令是: net stop mysql #關閉mysql net start mysql #開啟m

MySQL [ERROR] Table 'mysql.user' doesn't exist

    一次原始碼新裝的mysql,由於沒有複製my-default.cnf到/etc/my.cnf位置,在啟動mysql的時候碰到了無法開啟mysql.user表的錯誤。具體錯誤為:[ERROR] F

ERROR 1146 (42S02): Table 'performance_schema.session_variables' doesn't exist

之前mysql升級後使用show variables出現該錯誤,需要進行mysql_upgrade操作進行修復。 1)首先退出mysql 2)在命令列介面輸入: mysql_upgrade -uroot -p --force 3)然後重啟mysql即可 windows

【已解決】msyql 5.7.22 啟動服務 3534錯誤 table mysql.plugin doesnt exist

記錄下mysql5.0升級到5.7.22後,啟動服務報錯的解決方法。 【需求】:mysql5.0升級到5.7.22版本 【安裝環境】:系統:window7。安裝目錄:D:\Work_Program_Files\mysql。   my.ini配置如下: [mys

修復mysql:[ERROR] Native table ‘performance_schema’

data- 驗證 eve nbsp mar usr rwlock wait 地址 轉: http://www.amznz.com/error-native-table-performance_schema/ mysql數據庫出現如下錯誤,主要是因為升級了mysql軟件包

Error code:1728 Cannot load from mysql.proc. The table is probably corrupted

modify pos dsm enc from default php bug cor Error code:1728 Cannot load from mysql.proc. The table is probably corrupted http://bugs.m

Mysql數據庫的使用總結之ERROR 1146 (42S02)

命令 是否 存儲 不用 有一個 替換 服務 tables mysql 轉自:http://jazka.blog.51cto.com/809003/330418/ 在使用mysql數據庫過程中,遇到了錯誤ERROR 1146 (42S02):Table doesn’t e

TP5錯誤:SQLSTATE[42S02]: Base table or view not found: 1146 Table 'blog.tp_' doesn't exist

TP中,出現SQLSTATE[42S02]: Base table or view not found: 1146 Table 'blog.tp_' doesn't exist這樣的錯誤提示,是因為驗證規則中,出現錯誤 namespace app\admin\validate; use th

mysql [ERROR] Fatal error: mysql.user table is damaged or in unsupported 3.20 format.

在  Mac OS X裡的 mariadb 無法啟動,執行 mysql.server start 會顯示 Error, Error message: 170502 15:04:31 mysqld_safe Starting mysqld daemon with databases from /usr/loc

mysqlerror LNK2019: 無法解析的外部符號”的幾種可能原因

error LNK2019: 無法解析的外部符號這個錯之前見過很多次,能知道最根本的原因在於連結過程中沒有搜尋到程式用到的庫檔案,即*.lib。 筆記本重灌了系統,有32Bit升到64Bit,執行VTK程式時,始終報錯如下: 1> 正在建立

ERROR 1449 (HY000): The user specified as a definer ('mysql.infoschema'@'localhost') does not exist

Mysql Error:The user specified as a definer (‘mysql.infoschema’@’localhost’) does not exist’ when trying to dump tablespaces 我的MYSQL 使用Do

(win環境)Mysql Error:The user specified as a definer (‘mysql.infoschema’@’localhost’) does not exist

網上的了類似問題: The user specified as a definer ('root'@'%') does not exist 解決方法: mysql -u root -p 你的密碼 mysql>grant all privileges on

mysql無法啟動(Table 'mysql.plugin' doesn't exist)

151226 17:49:20 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql /usr/libexec/mysqld: Table 'mysql.plugin' doe

Mysql資料庫的使用總結之ERROR 1146 (42S02)

網上查詢解決辦法時,發現也有不少人有這個問題,而按照停止服務再拷貝的方式還是不行(我剛開始也不行,不過後來就好了,怪了,不知道為什麼)。所以這裡再說一種方法。首先在自己的mysql下,建立一個你即將要拷貝的資料庫(資料庫名要一樣,裡面不需要建表),然後將所有的.frm檔案拷貝到你建的資料庫資料夾下,此時再次進