srv0start.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:16k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /************************************************************************
  2. Starts the Innobase database server
  3. (c) 1996-2000 Innobase Oy
  4. Created 2/16/1996 Heikki Tuuri
  5. *************************************************************************/
  6. #include "os0proc.h"
  7. #include "sync0sync.h"
  8. #include "ut0mem.h"
  9. #include "mem0mem.h"
  10. #include "mem0pool.h"
  11. #include "data0data.h"
  12. #include "data0type.h"
  13. #include "dict0dict.h"
  14. #include "buf0buf.h"
  15. #include "buf0flu.h"
  16. #include "buf0rea.h"
  17. #include "os0file.h"
  18. #include "os0thread.h"
  19. #include "fil0fil.h"
  20. #include "fsp0fsp.h"
  21. #include "rem0rec.h"
  22. #include "rem0cmp.h"
  23. #include "mtr0mtr.h"
  24. #include "log0log.h"
  25. #include "log0recv.h"
  26. #include "page0page.h"
  27. #include "page0cur.h"
  28. #include "trx0trx.h"
  29. #include "dict0boot.h"
  30. #include "trx0sys.h"
  31. #include "dict0crea.h"
  32. #include "btr0btr.h"
  33. #include "btr0pcur.h"
  34. #include "btr0cur.h"
  35. #include "btr0sea.h"
  36. #include "rem0rec.h"
  37. #include "srv0srv.h"
  38. #include "que0que.h"
  39. #include "com0com.h"
  40. #include "usr0sess.h"
  41. #include "lock0lock.h"
  42. #include "trx0roll.h"
  43. #include "trx0purge.h"
  44. #include "row0ins.h"
  45. #include "row0sel.h"
  46. #include "row0upd.h"
  47. #include "row0row.h"
  48. #include "row0mysql.h"
  49. #include "lock0lock.h"
  50. #include "ibuf0ibuf.h"
  51. #include "pars0pars.h"
  52. #include "btr0sea.h"
  53. #include "srv0start.h"
  54. #include "que0que.h"
  55. ibool           srv_is_being_started = FALSE;
  56. ibool           srv_was_started      = FALSE;
  57. ibool measure_cont = FALSE;
  58. os_file_t files[1000];
  59. mutex_t ios_mutex;
  60. ulint ios;
  61. #define SRV_MAX_N_IO_THREADS 1000
  62. ulint n[SRV_MAX_N_IO_THREADS + 5];
  63. os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 5];
  64. #define SRV_N_PENDING_IOS_PER_THREAD  OS_AIO_N_PENDING_IOS_PER_THREAD
  65. #define SRV_MAX_N_PENDING_SYNC_IOS 100
  66. #define SRV_MAX_N_OPEN_FILES 25
  67. #define SRV_LOG_SPACE_FIRST_ID 1000000000
  68. /************************************************************************
  69. I/o-handler thread function. */
  70. static
  71. #ifndef __WIN__
  72. void*
  73. #else
  74. ulint
  75. #endif
  76. io_handler_thread(
  77. /*==============*/
  78. void* arg)
  79. {
  80. ulint segment;
  81. ulint i;
  82. segment = *((ulint*)arg);
  83. /* printf("Io handler thread %lu startsn", segment); */
  84. for (i = 0;; i++) {
  85. fil_aio_wait(segment);
  86. mutex_enter(&ios_mutex);
  87. ios++;
  88. mutex_exit(&ios_mutex);
  89. }
  90. #ifndef __WIN__
  91. return(NULL);
  92. #else
  93. return(0);
  94. #endif
  95. }
  96. /*************************************************************************
  97. Creates or opens the log files. */
  98. static
  99. ulint
  100. open_or_create_log_file(
  101. /*====================*/
  102. /* out: DB_SUCCESS or error code */
  103. ibool create_new_db, /* in: TRUE if we should create a
  104. new database */
  105. ibool* log_file_created, /* out: TRUE if new log file
  106. created */
  107. ulint k, /* in: log group number */
  108. ulint i) /* in: log file number in group */
  109. {
  110. ibool ret;
  111. ulint arch_space_id;
  112. ulint size;
  113. ulint size_high;
  114. char name[10000];
  115. UT_NOT_USED(create_new_db);
  116. *log_file_created = FALSE;
  117. sprintf(name, "%s%s%lu", srv_log_group_home_dirs[k], "ib_logfile", i);
  118. files[i] = os_file_create(name, OS_FILE_CREATE, OS_FILE_NORMAL, &ret);
  119. if (ret == FALSE) {
  120. if (os_file_get_last_error() != OS_FILE_ALREADY_EXISTS) {
  121. fprintf(stderr,
  122. "Innobase: Error in creating or opening %sn", name);
  123. return(DB_ERROR);
  124. }
  125. files[i] = os_file_create(
  126. name, OS_FILE_OPEN, OS_FILE_AIO, &ret);
  127. if (!ret) {
  128. fprintf(stderr,
  129. "Innobase: Error in opening %sn", name);
  130. return(DB_ERROR);
  131. }
  132. ret = os_file_get_size(files[i], &size, &size_high);
  133. ut_a(ret);
  134. if (size != UNIV_PAGE_SIZE * srv_log_file_size
  135. || size_high != 0) {
  136. fprintf(stderr,
  137. "Innobase: Error: log file %s is of different sizen"
  138. "Innobase: than specified in the .cnf file!n", name);
  139. return(DB_ERROR);
  140. }
  141. } else {
  142. *log_file_created = TRUE;
  143. fprintf(stderr,
  144. "Innobase: Log file %s did not exist: new to be createdn",
  145. name);
  146. printf("Innobase: Setting log file %s size to %lun",
  147.              name, UNIV_PAGE_SIZE * srv_log_file_size);
  148. ret = os_file_set_size(name, files[i],
  149. UNIV_PAGE_SIZE * srv_log_file_size, 0);
  150. if (!ret) {
  151. fprintf(stderr,
  152. "Innobase: Error in creating %s: probably out of disk spacen",
  153. name);
  154. return(DB_ERROR);
  155. }
  156. }
  157. ret = os_file_close(files[i]);
  158. ut_a(ret);
  159. if (i == 0) {
  160. /* Create in memory the file space object
  161. which is for this log group */
  162. fil_space_create(name,
  163. 2 * k + SRV_LOG_SPACE_FIRST_ID, FIL_LOG);
  164. }
  165. ut_a(fil_validate());
  166. fil_node_create(name, srv_log_file_size,
  167. 2 * k + SRV_LOG_SPACE_FIRST_ID);
  168. /* If this is the first log group, create the file space object
  169. for archived logs */
  170. if (k == 0 && i == 0) {
  171. arch_space_id = 2 * k + 1 + SRV_LOG_SPACE_FIRST_ID;
  172.      fil_space_create("arch_log_space", arch_space_id,
  173. FIL_LOG);
  174. } else {
  175. arch_space_id = ULINT_UNDEFINED;
  176. }
  177. if (i == 0) {
  178. log_group_init(k, srv_n_log_files,
  179. srv_log_file_size * UNIV_PAGE_SIZE,
  180. 2 * k + SRV_LOG_SPACE_FIRST_ID,
  181. arch_space_id);
  182. }
  183. return(DB_SUCCESS);
  184. }
  185. /*************************************************************************
  186. Creates or opens database data files. */
  187. static
  188. ulint
  189. open_or_create_data_files(
  190. /*======================*/
  191. /* out: DB_SUCCESS or error code */
  192. ibool* create_new_db, /* out: TRUE if new database should be
  193. created */
  194. dulint* min_flushed_lsn,/* out: min of flushed lsn values in data
  195. files */
  196. ulint* min_arch_log_no,/* out: min of archived log numbers in data
  197. files */
  198. dulint* max_flushed_lsn,/* out: */
  199. ulint* max_arch_log_no,/* out: */
  200. ulint* sum_of_new_sizes)/* out: sum of sizes of the new files added */
  201. {
  202. ibool ret;
  203. ulint i;
  204. ibool one_opened = FALSE;
  205. ibool one_created = FALSE;
  206. ulint size;
  207. ulint size_high;
  208. char name[10000];
  209. ut_a(srv_n_data_files < 1000);
  210. *sum_of_new_sizes = 0;
  211. *create_new_db = FALSE;
  212. for (i = 0; i < srv_n_data_files; i++) {
  213. sprintf(name, "%s%s", srv_data_home, srv_data_file_names[i]);
  214. files[i] = os_file_create(name, OS_FILE_CREATE,
  215. OS_FILE_NORMAL, &ret);
  216. if (ret == FALSE) {
  217. if (os_file_get_last_error() !=
  218. OS_FILE_ALREADY_EXISTS) {
  219. fprintf(stderr,
  220. "Innobase: Error in creating or opening %sn",
  221. name);
  222. return(DB_ERROR);
  223. }
  224. if (one_created) {
  225. fprintf(stderr,
  226. "Innobase: Error: data files can only be added at the endn");
  227. fprintf(stderr,
  228. "Innobase: of a tablespace, but data file %s existed beforehand.n",
  229. name);
  230. return(DB_ERROR);
  231. }
  232. files[i] = os_file_create(
  233. name, OS_FILE_OPEN, OS_FILE_NORMAL, &ret);
  234. if (!ret) {
  235. fprintf(stderr,
  236. "Innobase: Error in opening %sn", name);
  237. return(DB_ERROR);
  238. }
  239. ret = os_file_get_size(files[i], &size, &size_high);
  240. ut_a(ret);
  241. if (size != UNIV_PAGE_SIZE * srv_data_file_sizes[i]
  242.      || size_high != 0) {
  243. fprintf(stderr,
  244. "Innobase: Error: data file %s is of different sizen"
  245. "Innobase: than specified in the .cnf file!n", name);
  246. return(DB_ERROR);
  247. }
  248. fil_read_flushed_lsn_and_arch_log_no(files[i],
  249. one_opened,
  250. min_flushed_lsn, min_arch_log_no,
  251. max_flushed_lsn, max_arch_log_no);
  252. one_opened = TRUE;
  253. } else {
  254. one_created = TRUE;
  255. if (i > 0) {
  256. fprintf(stderr, 
  257. "Innobase: Data file %s did not exist: new to be createdn", name);
  258. } else {
  259. fprintf(stderr, 
  260.   "Innobase: The first specified data file %s did not exist:n"
  261. "Innobase: a new database to be created!n", name);
  262. *create_new_db = TRUE;
  263. }
  264. printf("Innobase: Setting file %s size to %lun",
  265.        name, UNIV_PAGE_SIZE * srv_data_file_sizes[i]);
  266. printf(
  267.     "Innobase: Database physically writes the file full: wait...n");
  268. ret = os_file_set_size(name, files[i],
  269. UNIV_PAGE_SIZE * srv_data_file_sizes[i], 0);
  270. if (!ret) {
  271. fprintf(stderr, 
  272. "Innobase: Error in creating %s: probably out of disk spacen", name);
  273. return(DB_ERROR);
  274. }
  275. *sum_of_new_sizes = *sum_of_new_sizes
  276. + srv_data_file_sizes[i];
  277. }
  278. ret = os_file_close(files[i]);
  279. ut_a(ret);
  280. if (i == 0) {
  281. fil_space_create(name, 0, FIL_TABLESPACE);
  282. }
  283. ut_a(fil_validate());
  284. fil_node_create(name, srv_data_file_sizes[i], 0);
  285. }
  286. ios = 0;
  287. mutex_create(&ios_mutex);
  288. mutex_set_level(&ios_mutex, SYNC_NO_ORDER_CHECK);
  289. return(DB_SUCCESS);
  290. }
  291. /*********************************************************************
  292. This thread is used to measure contention of latches. */
  293. static
  294. ulint
  295. test_measure_cont(
  296. /*==============*/
  297. void* arg)
  298. {
  299. ulint i, j;
  300. ulint pcount, kcount, s_scount, s_xcount, s_mcount, lcount;
  301. UT_NOT_USED(arg);
  302. fprintf(stderr, "Starting contention measurementn");
  303. for (i = 0; i < 1000; i++) {
  304. pcount = 0;
  305. kcount = 0;
  306. s_scount = 0;
  307. s_xcount = 0;
  308. s_mcount = 0;
  309. lcount = 0;
  310. for (j = 0; j < 100; j++) {
  311.     if (srv_measure_by_spin) {
  312.      ut_delay(ut_rnd_interval(0, 20000));
  313.     } else {
  314.      os_thread_sleep(20000);
  315.     }
  316.     if (kernel_mutex.lock_word) {
  317. kcount++;
  318.     }
  319.     if (buf_pool->mutex.lock_word) {
  320.      pcount++;
  321.     }
  322.     if (log_sys->mutex.lock_word) {
  323.      lcount++;
  324.     }
  325.     if (btr_search_latch.reader_count) {
  326.      s_scount++;
  327.     }
  328.     if (btr_search_latch.writer != RW_LOCK_NOT_LOCKED) {
  329.      s_xcount++;
  330.     }
  331.     if (btr_search_latch.mutex.lock_word) {
  332.      s_mcount++;
  333.     }
  334. }
  335. fprintf(stderr, 
  336. "Mutex res. l %lu, p %lu, k %lu s x %lu s s %lu s mut %lu of %lun",
  337. lcount, pcount, kcount, s_xcount, s_scount, s_mcount, j);
  338. sync_print_wait_info();
  339. fprintf(stderr, 
  340.     "log i/o %lu n non sea %lu n succ %lu n h fail %lun",
  341. log_sys->n_log_ios, btr_cur_n_non_sea,
  342. btr_search_n_succ, btr_search_n_hash_fail);
  343. }
  344. return(0);
  345. }
  346. /********************************************************************
  347. Starts Innobase and creates a new database if database files
  348. are not found and the user wants. Server parameters are
  349. read from a file of name "srv_init" in the ib_home directory. */
  350. int
  351. innobase_start_or_create_for_mysql(void)
  352. /*====================================*/
  353. /* out: DB_SUCCESS or error code */
  354. {
  355. ulint i;
  356. ulint k;
  357. ulint err;
  358. ibool create_new_db;
  359. ibool log_file_created;
  360. ibool log_created = FALSE;
  361. ibool log_opened = FALSE;
  362. dulint min_flushed_lsn;
  363. dulint max_flushed_lsn;
  364. ulint min_arch_log_no;
  365. ulint max_arch_log_no;
  366. ibool start_archive;
  367. ulint   sum_of_new_sizes;
  368. mtr_t   mtr;
  369. log_do_write = TRUE;
  370. /* yydebug = TRUE; */
  371. srv_is_being_started = TRUE;
  372. os_aio_use_native_aio = srv_use_native_aio;
  373. err = srv_boot();
  374. if (err != DB_SUCCESS) {
  375. return((int) err);
  376. }
  377. #if !(defined(WIN_ASYNC_IO) || defined(POSIX_ASYNC_IO))
  378. /* In simulated aio we currently have use only for 4 threads */
  379. os_aio_use_native_aio = FALSE;
  380. srv_n_file_io_threads = 4;
  381. #endif
  382. #ifdef WIN_ASYNC_IO
  383. /* On NT always use aio */
  384. os_aio_use_native_aio = TRUE;
  385. #endif
  386. if (!os_aio_use_native_aio) {
  387. os_aio_init(4 * SRV_N_PENDING_IOS_PER_THREAD
  388. * srv_n_file_io_threads,
  389. srv_n_file_io_threads,
  390. SRV_MAX_N_PENDING_SYNC_IOS);
  391. } else {
  392. os_aio_init(SRV_N_PENDING_IOS_PER_THREAD
  393. * srv_n_file_io_threads,
  394. srv_n_file_io_threads,
  395. SRV_MAX_N_PENDING_SYNC_IOS);
  396. }
  397. fil_init(SRV_MAX_N_OPEN_FILES);
  398. buf_pool_init(srv_pool_size, srv_pool_size);
  399. fsp_init();
  400. log_init();
  401. lock_sys_create(srv_lock_table_size);
  402. #ifdef POSIX_ASYNC_IO
  403. if (os_aio_use_native_aio) {
  404. /* There is only one thread per async io array:
  405. one for ibuf i/o, one for log i/o, one for ordinary reads,
  406. one for ordinary writes; we need only 4 i/o threads */
  407. srv_n_file_io_threads = 4;
  408. }
  409. #endif
  410. /* Create i/o-handler threads: */
  411. for (i = 0; i < srv_n_file_io_threads; i++) {
  412. n[i] = i;
  413. os_thread_create(io_handler_thread, n + i, thread_ids + i);
  414.      }
  415. err = open_or_create_data_files(&create_new_db,
  416. &min_flushed_lsn, &min_arch_log_no,
  417. &max_flushed_lsn, &max_arch_log_no,
  418. &sum_of_new_sizes);
  419. if (err != DB_SUCCESS) {
  420.         fprintf(stderr, "Innobase: Could not open data filesn");
  421. return((int) err);
  422. }
  423. for (k = 0; k < srv_n_log_groups; k++) {
  424. for (i = 0; i < srv_n_log_files; i++) {
  425. err = open_or_create_log_file(create_new_db,
  426. &log_file_created, k, i);
  427. if (err != DB_SUCCESS) {
  428. return((int) err);
  429. }
  430. if (log_file_created) {
  431. log_created = TRUE;
  432. } else {
  433. log_opened = TRUE;
  434. }
  435. if ((log_opened && create_new_db)
  436.      || (log_opened && log_created)) {
  437. fprintf(stderr, 
  438. "Innobase: Error: all log files must be created at the same time.n"
  439. "Innobase: If you want bigger or smaller log files,n"
  440. "Innobase: shut down the database and make sure theren"
  441. "Innobase: were no errors in shutdown.n"
  442. "Innobase: Then delete the existing log files. Edit the .cnf filen"
  443. "Innobase: and start the database again.n");
  444. return(DB_ERROR);
  445. }
  446. }
  447. }
  448. if (log_created && !create_new_db && !srv_archive_recovery) {
  449. if (ut_dulint_cmp(max_flushed_lsn, min_flushed_lsn) != 0
  450. || max_arch_log_no != min_arch_log_no) {
  451. fprintf(stderr, 
  452. "Innobase: Cannot initialize created log files becausen"
  453. "Innobase: data files were not in sync with each othern"
  454. "Innobase: or the data files are corrupt./n");
  455. return(DB_ERROR);
  456. }
  457. if (ut_dulint_cmp(max_flushed_lsn, ut_dulint_create(0, 1000))
  458.     < 0) {
  459.      fprintf(stderr,
  460. "Innobase: Cannot initialize created log files becausen"
  461. "Innobase: data files are corrupt, or new data files weren"
  462. "Innobase: created when the database was started previousn"
  463. "Innobase: time but the database was not shut downn"
  464. "Innobase: normally after that.n");
  465. return(DB_ERROR);
  466. }
  467. mutex_enter(&(log_sys->mutex));
  468. recv_reset_logs(ut_dulint_align_down(max_flushed_lsn,
  469. OS_FILE_LOG_BLOCK_SIZE),
  470. max_arch_log_no + 1, TRUE);
  471. mutex_exit(&(log_sys->mutex));
  472. }
  473. sess_sys_init_at_db_start();
  474. if (create_new_db) {
  475. mtr_start(&mtr);
  476. fsp_header_init(0, sum_of_new_sizes, &mtr);
  477. mtr_commit(&mtr);
  478. trx_sys_create();
  479. dict_create();
  480. } else if (srv_archive_recovery) {
  481. fprintf(stderr,
  482. "Innobase: Starting archive recovery from a backup...n");
  483. err = recv_recovery_from_archive_start(
  484. min_flushed_lsn,
  485. srv_archive_recovery_limit_lsn,
  486. min_arch_log_no);
  487. if (err != DB_SUCCESS) {
  488. return(DB_ERROR);
  489. }
  490. trx_sys_init_at_db_start();
  491. dict_boot();
  492. recv_recovery_from_archive_finish();
  493. } else {
  494. /* We always try to do a recovery, even if the database had
  495. been shut down normally */
  496. err = recv_recovery_from_checkpoint_start(LOG_CHECKPOINT,
  497. ut_dulint_max,
  498. min_flushed_lsn,
  499. max_flushed_lsn);
  500. if (err != DB_SUCCESS) {
  501. return(DB_ERROR);
  502. }
  503. trx_sys_init_at_db_start();
  504. dict_boot();
  505. /* The following needs trx lists which are initialized in
  506. trx_sys_init_at_db_start */
  507. recv_recovery_from_checkpoint_finish();
  508. }
  509. if (!create_new_db && sum_of_new_sizes > 0) {
  510. /* New data file(s) were added */
  511. mtr_start(&mtr);
  512. fsp_header_inc_size(0, sum_of_new_sizes, &mtr);
  513. mtr_commit(&mtr);
  514. }
  515. log_make_checkpoint_at(ut_dulint_max, TRUE);
  516. if (!srv_log_archive_on) {
  517. ut_a(DB_SUCCESS == log_archive_noarchivelog());
  518. } else {
  519. mutex_enter(&(log_sys->mutex));
  520. start_archive = FALSE;
  521. if (log_sys->archiving_state == LOG_ARCH_OFF) {
  522. start_archive = TRUE;
  523. }
  524. mutex_exit(&(log_sys->mutex));
  525. if (start_archive) {
  526. ut_a(DB_SUCCESS == log_archive_archivelog());
  527. }
  528. }
  529. if (srv_measure_contention) {
  530.   /* os_thread_create(&test_measure_cont, NULL, thread_ids +
  531.                                    SRV_MAX_N_IO_THREADS); */
  532. }
  533. /* Create the master thread which monitors the database
  534. server, and does purge and other utility operations */
  535. os_thread_create(&srv_master_thread, NULL, thread_ids + 1 +
  536. SRV_MAX_N_IO_THREADS);
  537. /* fprintf(stderr, "Max allowed record size %lun",
  538. page_get_free_space_of_empty() / 2); */
  539. /* Create the thread which watches the timeouts for lock waits */
  540. os_thread_create(&srv_lock_timeout_monitor_thread, NULL,
  541. thread_ids + 2 + SRV_MAX_N_IO_THREADS);
  542. fprintf(stderr, "Innobase: Startedn");
  543. srv_was_started = TRUE;
  544. srv_is_being_started = FALSE;
  545. sync_order_checks_on = TRUE;
  546. /* buf_debug_prints = TRUE; */
  547. return((int) DB_SUCCESS);
  548. }
  549. /********************************************************************
  550. Shuts down the Innobase database. */
  551. int
  552. innobase_shutdown_for_mysql(void) 
  553. /*=============================*/
  554. /* out: DB_SUCCESS or error code */
  555. {
  556.         if (!srv_was_started) {
  557.   if (srv_is_being_started) {
  558.             fprintf(stderr, 
  559. "Innobase: Warning: shutting down not properly started databasen");
  560.   }
  561.   return(DB_SUCCESS);
  562. }
  563. /* Flush buffer pool to disk, write the current lsn to
  564. the tablespace header(s), and copy all log data to archive */
  565. logs_empty_and_mark_files_at_shutdown();
  566. return((int) DB_SUCCESS);
  567. }