2011-02-16 149 views
5

我想有人試圖模擬有第二個auto_increment值。剛剛升級到MySQL 5.5.9爲什麼這個MySQL觸發器會導致堆棧溢出?

CREATE TABLE `job_title` (
    `job_id` int(11) NOT NULL AUTO_INCREMENT, 
    `position_id` int(11) DEFAULT NULL, 
    `title` varchar(255) COLLATE latin1_general_cs NOT NULL, 
    `selectable` tinyint(4) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`job_id`), 
    UNIQUE KEY `title` (`title`) 
) ENGINE=InnoDB; 

create trigger job_position_trigger 
    before insert on job_title for each row 
begin 
    if new.position_id is null then 
    set @position = (select max(position_id)+1 from job_title); 
    set new.position_id = @position; 
    end if; 
end 

錯誤:Thread stack overrun: 9024 bytes used of a 131072 byte stack, and 128000 bytes needed. Use 'mysqld --thread_stack=#' to specify a bigger stack.' on query. Default database: 'mydb'. Query: 'insert ignore into job_title (title) values ('Morning Show Personality')

+0

我跑了它沒有抱怨 – RichardTheKiwi

+0

工作的同樣的東西你使用的是MySQL 5.5嗎? –

+2

@nick酷名:) –

回答

1

在MySQL 5.1中我無法引起溢出堆棧,但[position_id]字段從未被觸發設置。它從來沒有設置的原因是,當你在空表上執行MAX(position_id)+ 1或在[position_id]列中只有NULL時,你的@position變量將被設置爲NULL。我不知道這是否導致觸發器重新評估自己(看到[position_id]仍然爲空),所以它反覆調用自己導致堆棧溢出。您可以嘗試的一種方法是更改​​觸發器以檢查null @position值,並在分配值之前將其強制爲「1」。

create trigger job_position_trigger 
    before insert on job_title for each row 
begin  
    if new.position_id is null then  
     set @position = (select max(position_id)+1 from job_title); 
     if @position is null then set @position = 1; end if; 
     set new.position_id = @position;  
    end if; 
end; 
+0

這是我的第一個想法。 – Ben

10

今天我遇到了同樣的問題,每次觸發都會導致堆棧溢出。原來我的Zend社區服務器安裝附帶了其中thread_stack大小設置爲128K默認的my.cnf文件,導致可用於堆棧中的每個線程131072個字節:

mysql> show variables where `Variable_name` = 'thread_stack'; 
+---------------+--------+ 
| Variable_name | Value | 
+---------------+--------+ 
| thread_stack | 131072 | 
+---------------+--------+ 

所以我註釋掉在/usr/local/zend/mysql/data/my.cnf行,重新啓動mysql守護進程,瞧!該default 192K是

mysql> show variables where `Variable_name` = 'thread_stack'; 
+---------------+--------+ 
| Variable_name | Value | 
+---------------+--------+ 
| thread_stack | 196608 | 
+---------------+--------+ 

現在你的表& tchester的觸發工作完美:)(千萬注意雖然分隔符)

mysql> CREATE TABLE `job_title` (
    -> `job_id` int(11) NOT NULL AUTO_INCREMENT, 
    -> `position_id` int(11) DEFAULT NULL, 
    -> `title` varchar(255) COLLATE latin1_general_cs NOT NULL, 
    -> `selectable` tinyint(4) NOT NULL DEFAULT '0', 
    -> PRIMARY KEY (`job_id`), 
    -> UNIQUE KEY `title` (`title`) 
    ->) ENGINE=InnoDB; 
Query OK, 0 rows affected (0.14 sec) 

mysql> DELIMITER && 
mysql> create trigger job_position_trigger 
    -> before insert on job_title for each row 
    -> begin  
    ->  if new.position_id is null then  
    ->  set @position = (select max(position_id)+1 from job_title); 
    ->  if @position is null then set @position = 1; end if; 
    ->  set new.position_id = @position;  
    ->  end if; 
    -> end; 
    -> && 
Query OK, 0 rows affected (0.29 sec) 

mysql> DELIMITER ; 
mysql> insert into job_title (title, selectable) values ("test", 1); 
Query OK, 1 row affected (0.00 sec) 

mysql> insert into job_title (title, selectable) values ("test2", 3); 
Query OK, 1 row affected (0.00 sec) 

mysql> select * from job_title; 
+--------+-------------+-------+------------+ 
| job_id | position_id | title | selectable | 
+--------+-------------+-------+------------+ 
|  1 |   1 | test |   1 | 
|  2 |   2 | test2 |   3 | 
+--------+-------------+-------+------------+ 
2 rows in set (0.00 sec) 

你得到了錯誤,使用了131072字節堆棧的9024個字節, 128000字節需要,是有道理的:9024 + 128000> 131072.

相關問題