这个错误时在Mysql主从配置产生的,最后找到这个Mysql的一个bug
http://bugs.mysql.com/bug.php?id=62055
bug的主要原因是:打开文件的函数中指定打开模式时,如果O_CREAT和O_EXCL同时指定,那么当文件存在时会导致打开文件出错,这个使用方法本来也没有什么错误,但是当使用Mysql主从备份机制,在一台服务器上安装多个mysqld实例时,就会出问题,代码在Mysql源码中/sql/slave.cc文件中,Mysql5.1.68是在2904行
/* Check the temporary directory used by commands like LOAD DATA INFILE. */ static int check_temp_dir(char* tmp_file) { int fd; MY_DIR *dirp; char tmp_dir[FN_REFLEN]; size_t tmp_dir_size; DBUG_ENTER("check_temp_dir"); /* Get the directory from the temporary file. */ dirname_part(tmp_dir, tmp_file, &tmp_dir_size); /* Check if the directory exists. */ if (!(dirp=my_dir(tmp_dir,MYF(MY_WME)))) DBUG_RETURN(1); my_dirend(dirp); /* Check permissions to create a file. */ if ((fd= my_create(tmp_file, CREATE_MODE, O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW, MYF(MY_WME))) < 0) DBUG_RETURN(1); /* Clean up. */ my_close(fd, MYF(0)); my_delete(tmp_file, MYF(0)); DBUG_RETURN(0); }
上面红色的是调用了一个函数打开文件,my_create,在这个函数中第三个参数传递了O_EXCL,但是并没有O_CREAT,下面继续看my_create函数,它在/mysys/my_create.c文件中定义
File my_create(const char *FileName, int CreateFlags, int access_flags, myf MyFlags) { int fd, rc; DBUG_ENTER("my_create"); DBUG_PRINT("my",("Name: '%s' CreateFlags: %d AccessFlags: %d MyFlags: %d", FileName, CreateFlags, access_flags, MyFlags)); #if !defined(NO_OPEN_3) fd = open((char *) FileName, access_flags | O_CREAT, CreateFlags ? CreateFlags : my_umask); #elif defined(VMS) fd = open((char *) FileName, access_flags | O_CREAT, 0, "ctx=stm","ctx=bin"); #elif defined(__WIN__) fd= my_sopen((char *) FileName, access_flags | O_CREAT | O_BINARY, SH_DENYNO, MY_S_IREAD | MY_S_IWRITE); #else fd = open(FileName, access_flags); #endif if ((MyFlags & MY_SYNC_DIR) && (fd >=0) && my_sync_dir_by_file(FileName, MyFlags)) { my_close(fd, MyFlags); fd= -1; } rc= my_register_filename(fd, FileName, FILE_BY_CREATE, EE_CANTCREATEFILE, MyFlags); /* my_register_filename() may fail on some platforms even if the call to *open() above succeeds. In this case, don't leave the stale file because callers assume the file to not exist if my_create() fails, so they don't do any cleanups. */ if (unlikely(fd >= 0 && rc < 0)) { int tmp= my_errno; my_delete(FileName, MyFlags); my_errno= tmp; } DBUG_RETURN(rc); } /* my_create */
红色的字体部分代码是为了实现跨平台,其中默认是蓝色字体代码,可以明显的看到,这时将O_CREAT添加进来了,此时就造成了O_CREAT和O_EXCL同时使用了。
在POSIX关于open函数的文档中可以看到,当O_CREAT和O_EXCL同时使用时,如果文件存在就会失败。
http://linux.die.net/man/3/open