現象:在線上環境,一條慢查詢沒有用到索引,表大小適中,加索引實際在3-5S內,決定在線添加。
mysql版本:5.1.56-community-log ,plugin innodb版本:1.0.15。
在添加索引的過程中,有原來的慢查詢對此表進行訪問,程序端返回錯誤:
"1412: Table definition has changed, please retry transaction (172.16.0.100)".
檢查錯誤日志,里面也記錄了相應的錯誤信息:
130324 3:55:55 [ERROR] Got error 159 when reading table './DB1/TB1' 130324 3:55:55 [ERROR] Got error 159 when reading table './DB1/TB1' 130324 3:55:55 [ERROR] Got error 159 when reading table './DB1/TB1'
分析159,1412錯誤,錯誤信息顯示說表定義已經改變了,要重做事務。
[root@devdb7 ~]# perror 159 MySQL error code 159: The table changed in storage engine [root@devdb7 ~]# perror 1412 MySQL error code 1412 (ER_TABLE_DEF_CHANGED): Table definition has changed, please retry transaction
分析:
Alter table tbname add index idx_X(column_name);是一個標准的Alter table 流程,引擎內部操作流程是:
1 If a transaction is open on this thread, commit it. 2 Acquire a read lock for the table. 3 Make a temporary table with new structure 4 Copy the old table to the temporary table row by row changing the structure of the rows on the fly. 5 Rename the original table out of the way 6 Rename the temporary table to the original table name. 7 Drop the original table. 8 Release the read lock.
在1-4步的過程中,別的session可以正常訪問這個表,到5的時候,會阻塞別的訪問,狀態提示是:“Waiting for tables”,然后等待。
前面1412的錯誤並不是這個。考慮到innodb 不是built in,而是plugin innodb,它實現了Fast Index Creation,是不是這個新特性造成的?
從mysql官方文檔可以看到
Prior to InnoDB storage engine 1.0.4, unexpected results could occur if a query attempts to use an index created after the start of the transaction containing the query. If an old transaction attempts to access a “too new” index,
InnoDB storage engine 1.0.4 and later reports an error: ERROR HY000: Table definition has changed, please retry transaction As the error message suggests, committing (or rolling back) the transaction, and restarting it, cures the problem.
在1.0.4或之后的innodb plugin里面,事務訪問新索引會提示1412信息,然后事務中斷。此錯誤並沒造成多大的影響,相對1.0.4之前的返回異常結果,已經做了優化了。
對於這樣的錯誤信息的處理方法是:As the error message suggests, committing (or rolling back) the transaction, and restarting it, cures the problem.
