~linuxjedi/drizzle/trunk-bug-667053

« back to all changes in this revision

Viewing changes to storage/innobase/srv/srv0srv.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************
 
2
The database server main program
 
3
 
 
4
NOTE: SQL Server 7 uses something which the documentation
 
5
calls user mode scheduled threads (UMS threads). One such
 
6
thread is usually allocated per processor. Win32
 
7
documentation does not know any UMS threads, which suggests
 
8
that the concept is internal to SQL Server 7. It may mean that
 
9
SQL Server 7 does all the scheduling of threads itself, even
 
10
in i/o waits. We should maybe modify InnoDB to use the same
 
11
technique, because thread switches within NT may be too slow.
 
12
 
 
13
SQL Server 7 also mentions fibers, which are cooperatively
 
14
scheduled threads. They can boost performance by 5 %,
 
15
according to the Delaney and Soukup's book.
 
16
 
 
17
Windows 2000 will have something called thread pooling
 
18
(see msdn website), which we could possibly use.
 
19
 
 
20
Another possibility could be to use some very fast user space
 
21
thread library. This might confuse NT though.
 
22
 
 
23
(c) 1995 Innobase Oy
 
24
 
 
25
Created 10/8/1995 Heikki Tuuri
 
26
*******************************************************/
 
27
/* Dummy comment */
 
28
#include "srv0srv.h"
 
29
 
 
30
#include "ut0mem.h"
 
31
#include "os0proc.h"
 
32
#include "mem0mem.h"
 
33
#include "mem0pool.h"
 
34
#include "sync0sync.h"
 
35
#include "thr0loc.h"
 
36
#include "que0que.h"
 
37
#include "srv0que.h"
 
38
#include "log0recv.h"
 
39
#include "pars0pars.h"
 
40
#include "usr0sess.h"
 
41
#include "lock0lock.h"
 
42
#include "trx0purge.h"
 
43
#include "ibuf0ibuf.h"
 
44
#include "buf0flu.h"
 
45
#include "btr0sea.h"
 
46
#include "dict0load.h"
 
47
#include "dict0boot.h"
 
48
#include "srv0start.h"
 
49
#include "row0mysql.h"
 
50
#include "ha_prototypes.h"
 
51
 
 
52
/* This is set to TRUE if the MySQL user has set it in MySQL; currently
 
53
affects only FOREIGN KEY definition parsing */
 
54
ibool   srv_lower_case_table_names      = FALSE;
 
55
 
 
56
/* The following counter is incremented whenever there is some user activity
 
57
in the server */
 
58
ulint   srv_activity_count      = 0;
 
59
 
 
60
/* The following is the maximum allowed duration of a lock wait. */
 
61
ulint   srv_fatal_semaphore_wait_threshold = 600;
 
62
 
 
63
/* How much data manipulation language (DML) statements need to be delayed,
 
64
in microseconds, in order to reduce the lagging of the purge thread. */
 
65
ulint   srv_dml_needed_delay = 0;
 
66
 
 
67
ibool   srv_lock_timeout_and_monitor_active = FALSE;
 
68
ibool   srv_error_monitor_active = FALSE;
 
69
 
 
70
const char*     srv_main_thread_op_info = "";
 
71
 
 
72
/* Prefix used by MySQL to indicate pre-5.1 table name encoding */
 
73
const char      srv_mysql50_table_name_prefix[9] = "#mysql50#";
 
74
 
 
75
/* Server parameters which are read from the initfile */
 
76
 
 
77
/* The following three are dir paths which are catenated before file
 
78
names, where the file name itself may also contain a path */
 
79
 
 
80
char*   srv_data_home   = NULL;
 
81
#ifdef UNIV_LOG_ARCHIVE
 
82
char*   srv_arch_dir    = NULL;
 
83
#endif /* UNIV_LOG_ARCHIVE */
 
84
 
 
85
ibool   srv_file_per_table = FALSE;     /* store to its own file each table
 
86
                                        created by an user; data dictionary
 
87
                                        tables are in the system tablespace
 
88
                                        0 */
 
89
ibool   srv_locks_unsafe_for_binlog = FALSE;    /* Place locks to
 
90
                                                records only i.e. do
 
91
                                                not use next-key
 
92
                                                locking except on
 
93
                                                duplicate key checking
 
94
                                                and foreign key
 
95
                                                checking */
 
96
ulint   srv_n_data_files = 0;
 
97
char**  srv_data_file_names = NULL;
 
98
ulint*  srv_data_file_sizes = NULL;     /* size in database pages */
 
99
 
 
100
ibool   srv_auto_extend_last_data_file  = FALSE; /* if TRUE, then we
 
101
                                                 auto-extend the last data
 
102
                                                 file */
 
103
ulint   srv_last_file_size_max  = 0;             /* if != 0, this tells
 
104
                                                 the max size auto-extending
 
105
                                                 may increase the last data
 
106
                                                 file size */
 
107
ulong   srv_auto_extend_increment = 8;           /* If the last data file is
 
108
                                                 auto-extended, we add this
 
109
                                                 many pages to it at a time */
 
110
ulint*  srv_data_file_is_raw_partition = NULL;
 
111
 
 
112
/* If the following is TRUE we do not allow inserts etc. This protects
 
113
the user from forgetting the 'newraw' keyword to my.cnf */
 
114
 
 
115
ibool   srv_created_new_raw     = FALSE;
 
116
 
 
117
char**  srv_log_group_home_dirs = NULL;
 
118
 
 
119
ulint   srv_n_log_groups        = ULINT_MAX;
 
120
ulint   srv_n_log_files         = ULINT_MAX;
 
121
ulint   srv_log_file_size       = ULINT_MAX;    /* size in database pages */
 
122
ulint   srv_log_buffer_size     = ULINT_MAX;    /* size in database pages */
 
123
ulong   srv_flush_log_at_trx_commit = 1;
 
124
 
 
125
byte    srv_latin1_ordering[256]        /* The sort order table of the latin1
 
126
                                        character set. The following table is
 
127
                                        the MySQL order as of Feb 10th, 2002 */
 
128
= {
 
129
  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
 
130
, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
 
131
, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
 
132
, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
 
133
, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27
 
134
, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F
 
135
, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37
 
136
, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F
 
137
, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47
 
138
, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F
 
139
, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57
 
140
, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F
 
141
, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47
 
142
, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F
 
143
, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57
 
144
, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F
 
145
, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87
 
146
, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F
 
147
, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97
 
148
, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F
 
149
, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7
 
150
, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF
 
151
, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7
 
152
, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF
 
153
, 0x41, 0x41, 0x41, 0x41, 0x5C, 0x5B, 0x5C, 0x43
 
154
, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49
 
155
, 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x5D, 0xD7
 
156
, 0xD8, 0x55, 0x55, 0x55, 0x59, 0x59, 0xDE, 0xDF
 
157
, 0x41, 0x41, 0x41, 0x41, 0x5C, 0x5B, 0x5C, 0x43
 
158
, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49
 
159
, 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x5D, 0xF7
 
160
, 0xD8, 0x55, 0x55, 0x55, 0x59, 0x59, 0xDE, 0xFF
 
161
};
 
162
 
 
163
ulint   srv_pool_size           = ULINT_MAX;    /* size in pages; MySQL inits
 
164
                                                this to size in kilobytes but
 
165
                                                we normalize this to pages in
 
166
                                                srv_boot() */
 
167
ulint   srv_awe_window_size     = 0;            /* size in pages; MySQL inits
 
168
                                                this to bytes, but we
 
169
                                                normalize it to pages in
 
170
                                                srv_boot() */
 
171
ulint   srv_mem_pool_size       = ULINT_MAX;    /* size in bytes */
 
172
ulint   srv_lock_table_size     = ULINT_MAX;
 
173
 
 
174
ulint   srv_n_file_io_threads   = ULINT_MAX;
 
175
 
 
176
#ifdef UNIV_LOG_ARCHIVE
 
177
ibool   srv_log_archive_on      = FALSE;
 
178
ibool   srv_archive_recovery    = 0;
 
179
dulint  srv_archive_recovery_limit_lsn;
 
180
#endif /* UNIV_LOG_ARCHIVE */
 
181
 
 
182
ulint   srv_lock_wait_timeout   = 1024 * 1024 * 1024;
 
183
 
 
184
/* This parameter is used to throttle the number of insert buffers that are
 
185
merged in a batch. By increasing this parameter on a faster disk you can
 
186
possibly reduce the number of I/O operations performed to complete the
 
187
merge operation. The value of this parameter is used as is by the
 
188
background loop when the system is idle (low load), on a busy system
 
189
the parameter is scaled down by a factor of 4, this is to avoid putting
 
190
a heavier load on the I/O sub system. */
 
191
 
 
192
ulong   srv_insert_buffer_batch_size = 20;
 
193
 
 
194
char*   srv_file_flush_method_str = NULL;
 
195
ulint   srv_unix_file_flush_method = SRV_UNIX_FSYNC;
 
196
ulint   srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
 
197
 
 
198
ulint   srv_max_n_open_files      = 300;
 
199
 
 
200
/* The InnoDB main thread tries to keep the ratio of modified pages
 
201
in the buffer pool to all database pages in the buffer pool smaller than
 
202
the following number. But it is not guaranteed that the value stays below
 
203
that during a time of heavy update/insert activity. */
 
204
 
 
205
ulong   srv_max_buf_pool_modified_pct   = 90;
 
206
 
 
207
/* variable counts amount of data read in total (in bytes) */
 
208
ulint srv_data_read = 0;
 
209
 
 
210
/* here we count the amount of data written in total (in bytes) */
 
211
ulint srv_data_written = 0;
 
212
 
 
213
/* the number of the log write requests done */
 
214
ulint srv_log_write_requests = 0;
 
215
 
 
216
/* the number of physical writes to the log performed */
 
217
ulint srv_log_writes = 0;
 
218
 
 
219
/* amount of data written to the log files in bytes */
 
220
ulint srv_os_log_written = 0;
 
221
 
 
222
/* amount of writes being done to the log files */
 
223
ulint srv_os_log_pending_writes = 0;
 
224
 
 
225
/* we increase this counter, when there we don't have enough space in the
 
226
log buffer and have to flush it */
 
227
ulint srv_log_waits = 0;
 
228
 
 
229
/* this variable counts the amount of times, when the doublewrite buffer
 
230
was flushed */
 
231
ulint srv_dblwr_writes = 0;
 
232
 
 
233
/* here we store the number of pages that have been flushed to the
 
234
doublewrite buffer */
 
235
ulint srv_dblwr_pages_written = 0;
 
236
 
 
237
/* in this variable we store the number of write requests issued */
 
238
ulint srv_buf_pool_write_requests = 0;
 
239
 
 
240
/* here we store the number of times when we had to wait for a free page
 
241
in the buffer pool. It happens when the buffer pool is full and we need
 
242
to make a flush, in order to be able to read or create a page. */
 
243
ulint srv_buf_pool_wait_free = 0;
 
244
 
 
245
/* variable to count the number of pages that were written from buffer
 
246
pool to the disk */
 
247
ulint srv_buf_pool_flushed = 0;
 
248
 
 
249
/* variable to count the number of buffer pool reads that led to the
 
250
reading of a disk page */
 
251
ulint srv_buf_pool_reads = 0;
 
252
 
 
253
/* variable to count the number of sequential read-aheads */
 
254
ulint srv_read_ahead_seq = 0;
 
255
 
 
256
/* variable to count the number of random read-aheads */
 
257
ulint srv_read_ahead_rnd = 0;
 
258
 
 
259
/* structure to pass status variables to MySQL */
 
260
export_struc export_vars;
 
261
 
 
262
/* If the following is != 0 we do not allow inserts etc. This protects
 
263
the user from forgetting the innodb_force_recovery keyword to my.cnf */
 
264
 
 
265
ulint   srv_force_recovery      = 0;
 
266
/*-----------------------*/
 
267
/* We are prepared for a situation that we have this many threads waiting for
 
268
a semaphore inside InnoDB. innobase_start_or_create_for_mysql() sets the
 
269
value. */
 
270
 
 
271
ulint   srv_max_n_threads       = 0;
 
272
 
 
273
/* The following controls how many threads we let inside InnoDB concurrently:
 
274
threads waiting for locks are not counted into the number because otherwise
 
275
we could get a deadlock. MySQL creates a thread for each user session, and
 
276
semaphore contention and convoy problems can occur withput this restriction.
 
277
Value 10 should be good if there are less than 4 processors + 4 disks in the
 
278
computer. Bigger computers need bigger values. Value 0 will disable the
 
279
concurrency check. */
 
280
 
 
281
ulong   srv_thread_concurrency  = 0;
 
282
ulong   srv_commit_concurrency  = 0;
 
283
 
 
284
os_fast_mutex_t srv_conc_mutex;         /* this mutex protects srv_conc data
 
285
                                        structures */
 
286
lint    srv_conc_n_threads      = 0;    /* number of OS threads currently
 
287
                                        inside InnoDB; it is not an error
 
288
                                        if this drops temporarily below zero
 
289
                                        because we do not demand that every
 
290
                                        thread increments this, but a thread
 
291
                                        waiting for a lock decrements this
 
292
                                        temporarily */
 
293
ulint   srv_conc_n_waiting_threads = 0; /* number of OS threads waiting in the
 
294
                                        FIFO for a permission to enter InnoDB
 
295
                                        */
 
296
 
 
297
typedef struct srv_conc_slot_struct     srv_conc_slot_t;
 
298
struct srv_conc_slot_struct{
 
299
        os_event_t                      event;          /* event to wait */
 
300
        ibool                           reserved;       /* TRUE if slot
 
301
                                                        reserved */
 
302
        ibool                           wait_ended;     /* TRUE when another
 
303
                                                        thread has already set
 
304
                                                        the event and the
 
305
                                                        thread in this slot is
 
306
                                                        free to proceed; but
 
307
                                                        reserved may still be
 
308
                                                        TRUE at that point */
 
309
        UT_LIST_NODE_T(srv_conc_slot_t) srv_conc_queue; /* queue node */
 
310
};
 
311
 
 
312
UT_LIST_BASE_NODE_T(srv_conc_slot_t)    srv_conc_queue; /* queue of threads
 
313
                                                        waiting to get in */
 
314
srv_conc_slot_t* srv_conc_slots;                        /* array of wait
 
315
                                                        slots */
 
316
 
 
317
/* Number of times a thread is allowed to enter InnoDB within the same
 
318
SQL query after it has once got the ticket at srv_conc_enter_innodb */
 
319
#define SRV_FREE_TICKETS_TO_ENTER srv_n_free_tickets_to_enter
 
320
#define SRV_THREAD_SLEEP_DELAY srv_thread_sleep_delay
 
321
/*-----------------------*/
 
322
/* If the following is set to 1 then we do not run purge and insert buffer
 
323
merge to completion before shutdown. If it is set to 2, do not even flush the
 
324
buffer pool to data files at the shutdown: we effectively 'crash'
 
325
InnoDB (but lose no committed transactions). */
 
326
ulint   srv_fast_shutdown       = 0;
 
327
 
 
328
/* Generate a innodb_status.<pid> file */
 
329
ibool   srv_innodb_status       = FALSE;
 
330
 
 
331
ibool   srv_stats_on_metadata   = TRUE;
 
332
 
 
333
ibool   srv_use_doublewrite_buf = TRUE;
 
334
ibool   srv_use_checksums = TRUE;
 
335
 
 
336
ibool   srv_set_thread_priorities = TRUE;
 
337
int     srv_query_thread_priority = 0;
 
338
 
 
339
/* TRUE if the Address Windowing Extensions of Windows are used; then we must
 
340
disable adaptive hash indexes */
 
341
ibool   srv_use_awe                     = FALSE;
 
342
ibool   srv_use_adaptive_hash_indexes   = TRUE;
 
343
 
 
344
/*-------------------------------------------*/
 
345
ulong   srv_n_spin_wait_rounds  = 20;
 
346
ulong   srv_n_free_tickets_to_enter = 500;
 
347
ulong   srv_thread_sleep_delay = 10000;
 
348
ulint   srv_spin_wait_delay     = 5;
 
349
ibool   srv_priority_boost      = TRUE;
 
350
 
 
351
ibool   srv_print_thread_releases       = FALSE;
 
352
ibool   srv_print_lock_waits            = FALSE;
 
353
ibool   srv_print_buf_io                = FALSE;
 
354
ibool   srv_print_log_io                = FALSE;
 
355
ibool   srv_print_latch_waits           = FALSE;
 
356
 
 
357
ulint           srv_n_rows_inserted             = 0;
 
358
ulint           srv_n_rows_updated              = 0;
 
359
ulint           srv_n_rows_deleted              = 0;
 
360
ulint           srv_n_rows_read                 = 0;
 
361
#ifndef UNIV_HOTBACKUP
 
362
static ulint    srv_n_rows_inserted_old         = 0;
 
363
static ulint    srv_n_rows_updated_old          = 0;
 
364
static ulint    srv_n_rows_deleted_old          = 0;
 
365
static ulint    srv_n_rows_read_old             = 0;
 
366
#endif /* !UNIV_HOTBACKUP */
 
367
 
 
368
ulint           srv_n_lock_wait_count           = 0;
 
369
ulint           srv_n_lock_wait_current_count   = 0;
 
370
ib_longlong     srv_n_lock_wait_time            = 0;
 
371
ulint           srv_n_lock_max_wait_time        = 0;
 
372
 
 
373
 
 
374
/*
 
375
  Set the following to 0 if you want InnoDB to write messages on
 
376
  stderr on startup/shutdown
 
377
*/
 
378
ibool   srv_print_verbose_log           = TRUE;
 
379
ibool   srv_print_innodb_monitor        = FALSE;
 
380
ibool   srv_print_innodb_lock_monitor   = FALSE;
 
381
ibool   srv_print_innodb_tablespace_monitor = FALSE;
 
382
ibool   srv_print_innodb_table_monitor = FALSE;
 
383
 
 
384
/* Array of English strings describing the current state of an
 
385
i/o handler thread */
 
386
 
 
387
const char* srv_io_thread_op_info[SRV_MAX_N_IO_THREADS];
 
388
const char* srv_io_thread_function[SRV_MAX_N_IO_THREADS];
 
389
 
 
390
time_t  srv_last_monitor_time;
 
391
 
 
392
mutex_t srv_innodb_monitor_mutex;
 
393
 
 
394
/* Mutex for locking srv_monitor_file */
 
395
mutex_t srv_monitor_file_mutex;
 
396
/* Temporary file for innodb monitor output */
 
397
FILE*   srv_monitor_file;
 
398
/* Mutex for locking srv_dict_tmpfile.
 
399
This mutex has a very high rank; threads reserving it should not
 
400
be holding any InnoDB latches. */
 
401
mutex_t srv_dict_tmpfile_mutex;
 
402
/* Temporary file for output from the data dictionary */
 
403
FILE*   srv_dict_tmpfile;
 
404
/* Mutex for locking srv_misc_tmpfile.
 
405
This mutex has a very low rank; threads reserving it should not
 
406
acquire any further latches or sleep before releasing this one. */
 
407
mutex_t srv_misc_tmpfile_mutex;
 
408
/* Temporary file for miscellanous diagnostic output */
 
409
FILE*   srv_misc_tmpfile;
 
410
 
 
411
ulint   srv_main_thread_process_no      = 0;
 
412
ulint   srv_main_thread_id              = 0;
 
413
 
 
414
/*
 
415
        IMPLEMENTATION OF THE SERVER MAIN PROGRAM
 
416
        =========================================
 
417
 
 
418
There is the following analogue between this database
 
419
server and an operating system kernel:
 
420
 
 
421
DB concept                      equivalent OS concept
 
422
----------                      ---------------------
 
423
transaction             --      process;
 
424
 
 
425
query thread            --      thread;
 
426
 
 
427
lock                    --      semaphore;
 
428
 
 
429
transaction set to
 
430
the rollback state      --      kill signal delivered to a process;
 
431
 
 
432
kernel                  --      kernel;
 
433
 
 
434
query thread execution:
 
435
(a) without kernel mutex
 
436
reserved                --      process executing in user mode;
 
437
(b) with kernel mutex reserved
 
438
                        --      process executing in kernel mode;
 
439
 
 
440
The server is controlled by a master thread which runs at
 
441
a priority higher than normal, that is, higher than user threads.
 
442
It sleeps most of the time, and wakes up, say, every 300 milliseconds,
 
443
to check whether there is anything happening in the server which
 
444
requires intervention of the master thread. Such situations may be,
 
445
for example, when flushing of dirty blocks is needed in the buffer
 
446
pool or old version of database rows have to be cleaned away.
 
447
 
 
448
The threads which we call user threads serve the queries of
 
449
the clients and input from the console of the server.
 
450
They run at normal priority. The server may have several
 
451
communications endpoints. A dedicated set of user threads waits
 
452
at each of these endpoints ready to receive a client request.
 
453
Each request is taken by a single user thread, which then starts
 
454
processing and, when the result is ready, sends it to the client
 
455
and returns to wait at the same endpoint the thread started from.
 
456
 
 
457
So, we do not have dedicated communication threads listening at
 
458
the endpoints and dealing the jobs to dedicated worker threads.
 
459
Our architecture saves one thread swithch per request, compared
 
460
to the solution with dedicated communication threads
 
461
which amounts to 15 microseconds on 100 MHz Pentium
 
462
running NT. If the client
 
463
is communicating over a network, this saving is negligible, but
 
464
if the client resides in the same machine, maybe in an SMP machine
 
465
on a different processor from the server thread, the saving
 
466
can be important as the threads can communicate over shared
 
467
memory with an overhead of a few microseconds.
 
468
 
 
469
We may later implement a dedicated communication thread solution
 
470
for those endpoints which communicate over a network.
 
471
 
 
472
Our solution with user threads has two problems: for each endpoint
 
473
there has to be a number of listening threads. If there are many
 
474
communication endpoints, it may be difficult to set the right number
 
475
of concurrent threads in the system, as many of the threads
 
476
may always be waiting at less busy endpoints. Another problem
 
477
is queuing of the messages, as the server internally does not
 
478
offer any queue for jobs.
 
479
 
 
480
Another group of user threads is intended for splitting the
 
481
queries and processing them in parallel. Let us call these
 
482
parallel communication threads. These threads are waiting for
 
483
parallelized tasks, suspended on event semaphores.
 
484
 
 
485
A single user thread waits for input from the console,
 
486
like a command to shut the database.
 
487
 
 
488
Utility threads are a different group of threads which takes
 
489
care of the buffer pool flushing and other, mainly background
 
490
operations, in the server.
 
491
Some of these utility threads always run at a lower than normal
 
492
priority, so that they are always in background. Some of them
 
493
may dynamically boost their priority by the pri_adjust function,
 
494
even to higher than normal priority, if their task becomes urgent.
 
495
The running of utilities is controlled by high- and low-water marks
 
496
of urgency. The urgency may be measured by the number of dirty blocks
 
497
in the buffer pool, in the case of the flush thread, for example.
 
498
When the high-water mark is exceeded, an utility starts running, until
 
499
the urgency drops under the low-water mark. Then the utility thread
 
500
suspend itself to wait for an event. The master thread is
 
501
responsible of signaling this event when the utility thread is
 
502
again needed.
 
503
 
 
504
For each individual type of utility, some threads always remain
 
505
at lower than normal priority. This is because pri_adjust is implemented
 
506
so that the threads at normal or higher priority control their
 
507
share of running time by calling sleep. Thus, if the load of the
 
508
system sudenly drops, these threads cannot necessarily utilize
 
509
the system fully. The background priority threads make up for this,
 
510
starting to run when the load drops.
 
511
 
 
512
When there is no activity in the system, also the master thread
 
513
suspends itself to wait for an event making
 
514
the server totally silent. The responsibility to signal this
 
515
event is on the user thread which again receives a message
 
516
from a client.
 
517
 
 
518
There is still one complication in our server design. If a
 
519
background utility thread obtains a resource (e.g., mutex) needed by a user
 
520
thread, and there is also some other user activity in the system,
 
521
the user thread may have to wait indefinitely long for the
 
522
resource, as the OS does not schedule a background thread if
 
523
there is some other runnable user thread. This problem is called
 
524
priority inversion in real-time programming.
 
525
 
 
526
One solution to the priority inversion problem would be to
 
527
keep record of which thread owns which resource and
 
528
in the above case boost the priority of the background thread
 
529
so that it will be scheduled and it can release the resource.
 
530
This solution is called priority inheritance in real-time programming.
 
531
A drawback of this solution is that the overhead of acquiring a mutex
 
532
increases slightly, maybe 0.2 microseconds on a 100 MHz Pentium, because
 
533
the thread has to call os_thread_get_curr_id.
 
534
This may be compared to 0.5 microsecond overhead for a mutex lock-unlock
 
535
pair. Note that the thread
 
536
cannot store the information in the resource, say mutex, itself,
 
537
because competing threads could wipe out the information if it is
 
538
stored before acquiring the mutex, and if it stored afterwards,
 
539
the information is outdated for the time of one machine instruction,
 
540
at least. (To be precise, the information could be stored to
 
541
lock_word in mutex if the machine supports atomic swap.)
 
542
 
 
543
The above solution with priority inheritance may become actual in the
 
544
future, but at the moment we plan to implement a more coarse solution,
 
545
which could be called a global priority inheritance. If a thread
 
546
has to wait for a long time, say 300 milliseconds, for a resource,
 
547
we just guess that it may be waiting for a resource owned by a background
 
548
thread, and boost the the priority of all runnable background threads
 
549
to the normal level. The background threads then themselves adjust
 
550
their fixed priority back to background after releasing all resources
 
551
they had (or, at some fixed points in their program code).
 
552
 
 
553
What is the performance of the global priority inheritance solution?
 
554
We may weigh the length of the wait time 300 milliseconds, during
 
555
which the system processes some other thread
 
556
to the cost of boosting the priority of each runnable background
 
557
thread, rescheduling it, and lowering the priority again.
 
558
On 100 MHz Pentium + NT this overhead may be of the order 100
 
559
microseconds per thread. So, if the number of runnable background
 
560
threads is not very big, say < 100, the cost is tolerable.
 
561
Utility threads probably will access resources used by
 
562
user threads not very often, so collisions of user threads
 
563
to preempted utility threads should not happen very often.
 
564
 
 
565
The thread table contains
 
566
information of the current status of each thread existing in the system,
 
567
and also the event semaphores used in suspending the master thread
 
568
and utility and parallel communication threads when they have nothing to do.
 
569
The thread table can be seen as an analogue to the process table
 
570
in a traditional Unix implementation.
 
571
 
 
572
The thread table is also used in the global priority inheritance
 
573
scheme. This brings in one additional complication: threads accessing
 
574
the thread table must have at least normal fixed priority,
 
575
because the priority inheritance solution does not work if a background
 
576
thread is preempted while possessing the mutex protecting the thread table.
 
577
So, if a thread accesses the thread table, its priority has to be
 
578
boosted at least to normal. This priority requirement can be seen similar to
 
579
the privileged mode used when processing the kernel calls in traditional
 
580
Unix.*/
 
581
 
 
582
/* Thread slot in the thread table */
 
583
struct srv_slot_struct{
 
584
        os_thread_id_t  id;             /* thread id */
 
585
        os_thread_t     handle;         /* thread handle */
 
586
        ulint           type;           /* thread type: user, utility etc. */
 
587
        ibool           in_use;         /* TRUE if this slot is in use */
 
588
        ibool           suspended;      /* TRUE if the thread is waiting
 
589
                                        for the event of this slot */
 
590
        ib_time_t       suspend_time;   /* time when the thread was
 
591
                                        suspended */
 
592
        os_event_t      event;          /* event used in suspending the
 
593
                                        thread when it has nothing to do */
 
594
        que_thr_t*      thr;            /* suspended query thread (only
 
595
                                        used for MySQL threads) */
 
596
};
 
597
 
 
598
/* Table for MySQL threads where they will be suspended to wait for locks */
 
599
srv_slot_t*     srv_mysql_table = NULL;
 
600
 
 
601
os_event_t      srv_lock_timeout_thread_event;
 
602
 
 
603
srv_sys_t*      srv_sys = NULL;
 
604
 
 
605
byte            srv_pad1[64];   /* padding to prevent other memory update
 
606
                                hotspots from residing on the same memory
 
607
                                cache line */
 
608
mutex_t*        kernel_mutex_temp;/* mutex protecting the server, trx structs,
 
609
                                query threads, and lock table */
 
610
byte            srv_pad2[64];   /* padding to prevent other memory update
 
611
                                hotspots from residing on the same memory
 
612
                                cache line */
 
613
 
 
614
/* The following three values measure the urgency of the jobs of
 
615
buffer, version, and insert threads. They may vary from 0 - 1000.
 
616
The server mutex protects all these variables. The low-water values
 
617
tell that the server can acquiesce the utility when the value
 
618
drops below this low-water mark. */
 
619
 
 
620
ulint   srv_meter[SRV_MASTER + 1];
 
621
ulint   srv_meter_low_water[SRV_MASTER + 1];
 
622
ulint   srv_meter_high_water[SRV_MASTER + 1];
 
623
ulint   srv_meter_high_water2[SRV_MASTER + 1];
 
624
ulint   srv_meter_foreground[SRV_MASTER + 1];
 
625
 
 
626
/* The following values give info about the activity going on in
 
627
the database. They are protected by the server mutex. The arrays
 
628
are indexed by the type of the thread. */
 
629
 
 
630
ulint   srv_n_threads_active[SRV_MASTER + 1];
 
631
ulint   srv_n_threads[SRV_MASTER + 1];
 
632
 
 
633
/*************************************************************************
 
634
Sets the info describing an i/o thread current state. */
 
635
 
 
636
void
 
637
srv_set_io_thread_op_info(
 
638
/*======================*/
 
639
        ulint           i,      /* in: the 'segment' of the i/o thread */
 
640
        const char*     str)    /* in: constant char string describing the
 
641
                                state */
 
642
{
 
643
        ut_a(i < SRV_MAX_N_IO_THREADS);
 
644
 
 
645
        srv_io_thread_op_info[i] = str;
 
646
}
 
647
 
 
648
/*************************************************************************
 
649
Accessor function to get pointer to n'th slot in the server thread
 
650
table. */
 
651
static
 
652
srv_slot_t*
 
653
srv_table_get_nth_slot(
 
654
/*===================*/
 
655
                                /* out: pointer to the slot */
 
656
        ulint   index)          /* in: index of the slot */
 
657
{
 
658
        ut_a(index < OS_THREAD_MAX_N);
 
659
 
 
660
        return(srv_sys->threads + index);
 
661
}
 
662
 
 
663
#ifndef UNIV_HOTBACKUP
 
664
/*************************************************************************
 
665
Gets the number of threads in the system. */
 
666
 
 
667
ulint
 
668
srv_get_n_threads(void)
 
669
/*===================*/
 
670
{
 
671
        ulint   i;
 
672
        ulint   n_threads       = 0;
 
673
 
 
674
        mutex_enter(&kernel_mutex);
 
675
 
 
676
        for (i = SRV_COM; i < SRV_MASTER + 1; i++) {
 
677
 
 
678
                n_threads += srv_n_threads[i];
 
679
        }
 
680
 
 
681
        mutex_exit(&kernel_mutex);
 
682
 
 
683
        return(n_threads);
 
684
}
 
685
 
 
686
/*************************************************************************
 
687
Reserves a slot in the thread table for the current thread. Also creates the
 
688
thread local storage struct for the current thread. NOTE! The server mutex
 
689
has to be reserved by the caller! */
 
690
static
 
691
ulint
 
692
srv_table_reserve_slot(
 
693
/*===================*/
 
694
                        /* out: reserved slot index */
 
695
        ulint   type)   /* in: type of the thread: one of SRV_COM, ... */
 
696
{
 
697
        srv_slot_t*     slot;
 
698
        ulint           i;
 
699
 
 
700
        ut_a(type > 0);
 
701
        ut_a(type <= SRV_MASTER);
 
702
 
 
703
        i = 0;
 
704
        slot = srv_table_get_nth_slot(i);
 
705
 
 
706
        while (slot->in_use) {
 
707
                i++;
 
708
                slot = srv_table_get_nth_slot(i);
 
709
        }
 
710
 
 
711
        ut_a(slot->in_use == FALSE);
 
712
 
 
713
        slot->in_use = TRUE;
 
714
        slot->suspended = FALSE;
 
715
        slot->id = os_thread_get_curr_id();
 
716
        slot->handle = os_thread_get_curr();
 
717
        slot->type = type;
 
718
 
 
719
        thr_local_create();
 
720
 
 
721
        thr_local_set_slot_no(os_thread_get_curr_id(), i);
 
722
 
 
723
        return(i);
 
724
}
 
725
 
 
726
/*************************************************************************
 
727
Suspends the calling thread to wait for the event in its thread slot.
 
728
NOTE! The server mutex has to be reserved by the caller! */
 
729
static
 
730
os_event_t
 
731
srv_suspend_thread(void)
 
732
/*====================*/
 
733
                        /* out: event for the calling thread to wait */
 
734
{
 
735
        srv_slot_t*     slot;
 
736
        os_event_t      event;
 
737
        ulint           slot_no;
 
738
        ulint           type;
 
739
 
 
740
        ut_ad(mutex_own(&kernel_mutex));
 
741
 
 
742
        slot_no = thr_local_get_slot_no(os_thread_get_curr_id());
 
743
 
 
744
        if (srv_print_thread_releases) {
 
745
                fprintf(stderr,
 
746
                        "Suspending thread %lu to slot %lu meter %lu\n",
 
747
                        (ulong) os_thread_get_curr_id(), (ulong) slot_no,
 
748
                        (ulong) srv_meter[SRV_RECOVERY]);
 
749
        }
 
750
 
 
751
        slot = srv_table_get_nth_slot(slot_no);
 
752
 
 
753
        type = slot->type;
 
754
 
 
755
        ut_ad(type >= SRV_WORKER);
 
756
        ut_ad(type <= SRV_MASTER);
 
757
 
 
758
        event = slot->event;
 
759
 
 
760
        slot->suspended = TRUE;
 
761
 
 
762
        ut_ad(srv_n_threads_active[type] > 0);
 
763
 
 
764
        srv_n_threads_active[type]--;
 
765
 
 
766
        os_event_reset(event);
 
767
 
 
768
        return(event);
 
769
}
 
770
#endif /* !UNIV_HOTBACKUP */
 
771
 
 
772
/*************************************************************************
 
773
Releases threads of the type given from suspension in the thread table.
 
774
NOTE! The server mutex has to be reserved by the caller! */
 
775
 
 
776
ulint
 
777
srv_release_threads(
 
778
/*================*/
 
779
                        /* out: number of threads released: this may be
 
780
                        < n if not enough threads were suspended at the
 
781
                        moment */
 
782
        ulint   type,   /* in: thread type */
 
783
        ulint   n)      /* in: number of threads to release */
 
784
{
 
785
        srv_slot_t*     slot;
 
786
        ulint           i;
 
787
        ulint           count   = 0;
 
788
 
 
789
        ut_ad(type >= SRV_WORKER);
 
790
        ut_ad(type <= SRV_MASTER);
 
791
        ut_ad(n > 0);
 
792
        ut_ad(mutex_own(&kernel_mutex));
 
793
 
 
794
        for (i = 0; i < OS_THREAD_MAX_N; i++) {
 
795
 
 
796
                slot = srv_table_get_nth_slot(i);
 
797
 
 
798
                if (slot->in_use && slot->type == type && slot->suspended) {
 
799
 
 
800
                        slot->suspended = FALSE;
 
801
 
 
802
                        srv_n_threads_active[type]++;
 
803
 
 
804
                        os_event_set(slot->event);
 
805
 
 
806
                        if (srv_print_thread_releases) {
 
807
                                fprintf(stderr,
 
808
                                        "Releasing thread %lu type %lu"
 
809
                                        " from slot %lu meter %lu\n",
 
810
                                        (ulong) slot->id, (ulong) type,
 
811
                                        (ulong) i,
 
812
                                        (ulong) srv_meter[SRV_RECOVERY]);
 
813
                        }
 
814
 
 
815
                        count++;
 
816
 
 
817
                        if (count == n) {
 
818
                                break;
 
819
                        }
 
820
                }
 
821
        }
 
822
 
 
823
        return(count);
 
824
}
 
825
 
 
826
/*************************************************************************
 
827
Returns the calling thread type. */
 
828
 
 
829
ulint
 
830
srv_get_thread_type(void)
 
831
/*=====================*/
 
832
                        /* out: SRV_COM, ... */
 
833
{
 
834
        ulint           slot_no;
 
835
        srv_slot_t*     slot;
 
836
        ulint           type;
 
837
 
 
838
        mutex_enter(&kernel_mutex);
 
839
 
 
840
        slot_no = thr_local_get_slot_no(os_thread_get_curr_id());
 
841
 
 
842
        slot = srv_table_get_nth_slot(slot_no);
 
843
 
 
844
        type = slot->type;
 
845
 
 
846
        ut_ad(type >= SRV_WORKER);
 
847
        ut_ad(type <= SRV_MASTER);
 
848
 
 
849
        mutex_exit(&kernel_mutex);
 
850
 
 
851
        return(type);
 
852
}
 
853
 
 
854
/*************************************************************************
 
855
Initializes the server. */
 
856
 
 
857
void
 
858
srv_init(void)
 
859
/*==========*/
 
860
{
 
861
        srv_conc_slot_t*        conc_slot;
 
862
        srv_slot_t*             slot;
 
863
        dict_table_t*           table;
 
864
        ulint                   i;
 
865
 
 
866
        srv_sys = mem_alloc(sizeof(srv_sys_t));
 
867
 
 
868
        kernel_mutex_temp = mem_alloc(sizeof(mutex_t));
 
869
        mutex_create(&kernel_mutex, SYNC_KERNEL);
 
870
 
 
871
        mutex_create(&srv_innodb_monitor_mutex, SYNC_NO_ORDER_CHECK);
 
872
 
 
873
        srv_sys->threads = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_slot_t));
 
874
 
 
875
        for (i = 0; i < OS_THREAD_MAX_N; i++) {
 
876
                slot = srv_table_get_nth_slot(i);
 
877
                slot->in_use = FALSE;
 
878
                slot->type=0;   /* Avoid purify errors */
 
879
                slot->event = os_event_create(NULL);
 
880
                ut_a(slot->event);
 
881
        }
 
882
 
 
883
        srv_mysql_table = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_slot_t));
 
884
 
 
885
        for (i = 0; i < OS_THREAD_MAX_N; i++) {
 
886
                slot = srv_mysql_table + i;
 
887
                slot->in_use = FALSE;
 
888
                slot->type = 0;
 
889
                slot->event = os_event_create(NULL);
 
890
                ut_a(slot->event);
 
891
        }
 
892
 
 
893
        srv_lock_timeout_thread_event = os_event_create(NULL);
 
894
 
 
895
        for (i = 0; i < SRV_MASTER + 1; i++) {
 
896
                srv_n_threads_active[i] = 0;
 
897
                srv_n_threads[i] = 0;
 
898
                srv_meter[i] = 30;
 
899
                srv_meter_low_water[i] = 50;
 
900
                srv_meter_high_water[i] = 100;
 
901
                srv_meter_high_water2[i] = 200;
 
902
                srv_meter_foreground[i] = 250;
 
903
        }
 
904
 
 
905
        UT_LIST_INIT(srv_sys->tasks);
 
906
 
 
907
        /* create dummy table and index for old-style infimum and supremum */
 
908
        table = dict_mem_table_create("SYS_DUMMY1",
 
909
                                      DICT_HDR_SPACE, 1, 0);
 
910
        dict_mem_table_add_col(table, NULL, NULL, DATA_CHAR,
 
911
                               DATA_ENGLISH | DATA_NOT_NULL, 8);
 
912
 
 
913
        srv_sys->dummy_ind1 = dict_mem_index_create(
 
914
                "SYS_DUMMY1", "SYS_DUMMY1", DICT_HDR_SPACE, 0, 1);
 
915
        dict_index_add_col(srv_sys->dummy_ind1, table, (dict_col_t*)
 
916
                           dict_table_get_nth_col(table, 0), 0);
 
917
        srv_sys->dummy_ind1->table = table;
 
918
        /* create dummy table and index for new-style infimum and supremum */
 
919
        table = dict_mem_table_create("SYS_DUMMY2",
 
920
                                      DICT_HDR_SPACE, 1, DICT_TF_COMPACT);
 
921
        dict_mem_table_add_col(table, NULL, NULL, DATA_CHAR,
 
922
                               DATA_ENGLISH | DATA_NOT_NULL, 8);
 
923
        srv_sys->dummy_ind2 = dict_mem_index_create(
 
924
                "SYS_DUMMY2", "SYS_DUMMY2", DICT_HDR_SPACE, 0, 1);
 
925
        dict_index_add_col(srv_sys->dummy_ind2, table, (dict_col_t*)
 
926
                           dict_table_get_nth_col(table, 0), 0);
 
927
        srv_sys->dummy_ind2->table = table;
 
928
 
 
929
        /* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */
 
930
        srv_sys->dummy_ind1->cached = srv_sys->dummy_ind2->cached = TRUE;
 
931
 
 
932
        /* Init the server concurrency restriction data structures */
 
933
 
 
934
        os_fast_mutex_init(&srv_conc_mutex);
 
935
 
 
936
        UT_LIST_INIT(srv_conc_queue);
 
937
 
 
938
        srv_conc_slots = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_conc_slot_t));
 
939
 
 
940
        for (i = 0; i < OS_THREAD_MAX_N; i++) {
 
941
                conc_slot = srv_conc_slots + i;
 
942
                conc_slot->reserved = FALSE;
 
943
                conc_slot->event = os_event_create(NULL);
 
944
                ut_a(conc_slot->event);
 
945
        }
 
946
}
 
947
 
 
948
/*************************************************************************
 
949
Frees the OS fast mutex created in srv_init(). */
 
950
 
 
951
void
 
952
srv_free(void)
 
953
/*==========*/
 
954
{
 
955
        os_fast_mutex_free(&srv_conc_mutex);
 
956
}
 
957
 
 
958
/*************************************************************************
 
959
Initializes the synchronization primitives, memory system, and the thread
 
960
local storage. */
 
961
 
 
962
void
 
963
srv_general_init(void)
 
964
/*==================*/
 
965
{
 
966
        os_sync_init();
 
967
        sync_init();
 
968
        mem_init(srv_mem_pool_size);
 
969
        thr_local_init();
 
970
}
 
971
 
 
972
/*======================= InnoDB Server FIFO queue =======================*/
 
973
 
 
974
/* Maximum allowable purge history length.  <=0 means 'infinite'. */
 
975
ulong   srv_max_purge_lag               = 0;
 
976
 
 
977
/*************************************************************************
 
978
Puts an OS thread to wait if there are too many concurrent threads
 
979
(>= srv_thread_concurrency) inside InnoDB. The threads wait in a FIFO queue. */
 
980
 
 
981
void
 
982
srv_conc_enter_innodb(
 
983
/*==================*/
 
984
        trx_t*  trx)    /* in: transaction object associated with the
 
985
                        thread */
 
986
{
 
987
        ibool                   has_slept = FALSE;
 
988
        srv_conc_slot_t*        slot      = NULL;
 
989
        ulint                   i;
 
990
 
 
991
        if (trx->mysql_thd != NULL
 
992
            && thd_is_replication_slave_thread(trx->mysql_thd)) {
 
993
 
 
994
                /* TODO Do something more interesting (based on a config
 
995
                parameter). Some users what to give the replication
 
996
                thread very low priority, see http://bugs.mysql.com/25078
 
997
                This can be done by introducing
 
998
                innodb_replication_delay(ms) config parameter */
 
999
                return;
 
1000
        }
 
1001
 
 
1002
        /* If trx has 'free tickets' to enter the engine left, then use one
 
1003
        such ticket */
 
1004
 
 
1005
        if (trx->n_tickets_to_enter_innodb > 0) {
 
1006
                trx->n_tickets_to_enter_innodb--;
 
1007
 
 
1008
                return;
 
1009
        }
 
1010
 
 
1011
        os_fast_mutex_lock(&srv_conc_mutex);
 
1012
retry:
 
1013
        if (trx->declared_to_be_inside_innodb) {
 
1014
                ut_print_timestamp(stderr);
 
1015
                fputs("  InnoDB: Error: trying to declare trx"
 
1016
                      " to enter InnoDB, but\n"
 
1017
                      "InnoDB: it already is declared.\n", stderr);
 
1018
                trx_print(stderr, trx, 0);
 
1019
                putc('\n', stderr);
 
1020
                os_fast_mutex_unlock(&srv_conc_mutex);
 
1021
 
 
1022
                return;
 
1023
        }
 
1024
 
 
1025
        if (srv_conc_n_threads < (lint)srv_thread_concurrency) {
 
1026
 
 
1027
                srv_conc_n_threads++;
 
1028
                trx->declared_to_be_inside_innodb = TRUE;
 
1029
                trx->n_tickets_to_enter_innodb = SRV_FREE_TICKETS_TO_ENTER;
 
1030
 
 
1031
                os_fast_mutex_unlock(&srv_conc_mutex);
 
1032
 
 
1033
                return;
 
1034
        }
 
1035
 
 
1036
        /* If the transaction is not holding resources, let it sleep
 
1037
        for SRV_THREAD_SLEEP_DELAY microseconds, and try again then */
 
1038
 
 
1039
        if (!has_slept && !trx->has_search_latch
 
1040
            && NULL == UT_LIST_GET_FIRST(trx->trx_locks)) {
 
1041
 
 
1042
                has_slept = TRUE; /* We let it sleep only once to avoid
 
1043
                                  starvation */
 
1044
 
 
1045
                srv_conc_n_waiting_threads++;
 
1046
 
 
1047
                os_fast_mutex_unlock(&srv_conc_mutex);
 
1048
 
 
1049
                trx->op_info = "sleeping before joining InnoDB queue";
 
1050
 
 
1051
                /* Peter Zaitsev suggested that we take the sleep away
 
1052
                altogether. But the sleep may be good in pathological
 
1053
                situations of lots of thread switches. Simply put some
 
1054
                threads aside for a while to reduce the number of thread
 
1055
                switches. */
 
1056
                if (SRV_THREAD_SLEEP_DELAY > 0) {
 
1057
                        os_thread_sleep(SRV_THREAD_SLEEP_DELAY);
 
1058
                }
 
1059
 
 
1060
                trx->op_info = "";
 
1061
 
 
1062
                os_fast_mutex_lock(&srv_conc_mutex);
 
1063
 
 
1064
                srv_conc_n_waiting_threads--;
 
1065
 
 
1066
                goto retry;
 
1067
        }
 
1068
 
 
1069
        /* Too many threads inside: put the current thread to a queue */
 
1070
 
 
1071
        for (i = 0; i < OS_THREAD_MAX_N; i++) {
 
1072
                slot = srv_conc_slots + i;
 
1073
 
 
1074
                if (!slot->reserved) {
 
1075
 
 
1076
                        break;
 
1077
                }
 
1078
        }
 
1079
 
 
1080
        if (i == OS_THREAD_MAX_N) {
 
1081
                /* Could not find a free wait slot, we must let the
 
1082
                thread enter */
 
1083
 
 
1084
                srv_conc_n_threads++;
 
1085
                trx->declared_to_be_inside_innodb = TRUE;
 
1086
                trx->n_tickets_to_enter_innodb = 0;
 
1087
 
 
1088
                os_fast_mutex_unlock(&srv_conc_mutex);
 
1089
 
 
1090
                return;
 
1091
        }
 
1092
 
 
1093
        /* Release possible search system latch this thread has */
 
1094
        if (trx->has_search_latch) {
 
1095
                trx_search_latch_release_if_reserved(trx);
 
1096
        }
 
1097
 
 
1098
        /* Add to the queue */
 
1099
        slot->reserved = TRUE;
 
1100
        slot->wait_ended = FALSE;
 
1101
 
 
1102
        UT_LIST_ADD_LAST(srv_conc_queue, srv_conc_queue, slot);
 
1103
 
 
1104
        os_event_reset(slot->event);
 
1105
 
 
1106
        srv_conc_n_waiting_threads++;
 
1107
 
 
1108
        os_fast_mutex_unlock(&srv_conc_mutex);
 
1109
 
 
1110
        /* Go to wait for the event; when a thread leaves InnoDB it will
 
1111
        release this thread */
 
1112
 
 
1113
        trx->op_info = "waiting in InnoDB queue";
 
1114
 
 
1115
        os_event_wait(slot->event);
 
1116
 
 
1117
        trx->op_info = "";
 
1118
 
 
1119
        os_fast_mutex_lock(&srv_conc_mutex);
 
1120
 
 
1121
        srv_conc_n_waiting_threads--;
 
1122
 
 
1123
        /* NOTE that the thread which released this thread already
 
1124
        incremented the thread counter on behalf of this thread */
 
1125
 
 
1126
        slot->reserved = FALSE;
 
1127
 
 
1128
        UT_LIST_REMOVE(srv_conc_queue, srv_conc_queue, slot);
 
1129
 
 
1130
        trx->declared_to_be_inside_innodb = TRUE;
 
1131
        trx->n_tickets_to_enter_innodb = SRV_FREE_TICKETS_TO_ENTER;
 
1132
 
 
1133
        os_fast_mutex_unlock(&srv_conc_mutex);
 
1134
}
 
1135
 
 
1136
/*************************************************************************
 
1137
This lets a thread enter InnoDB regardless of the number of threads inside
 
1138
InnoDB. This must be called when a thread ends a lock wait. */
 
1139
 
 
1140
void
 
1141
srv_conc_force_enter_innodb(
 
1142
/*========================*/
 
1143
        trx_t*  trx)    /* in: transaction object associated with the
 
1144
                        thread */
 
1145
{
 
1146
        if (UNIV_LIKELY(!srv_thread_concurrency)) {
 
1147
 
 
1148
                return;
 
1149
        }
 
1150
 
 
1151
        os_fast_mutex_lock(&srv_conc_mutex);
 
1152
 
 
1153
        srv_conc_n_threads++;
 
1154
        trx->declared_to_be_inside_innodb = TRUE;
 
1155
        trx->n_tickets_to_enter_innodb = 1;
 
1156
 
 
1157
        os_fast_mutex_unlock(&srv_conc_mutex);
 
1158
}
 
1159
 
 
1160
/*************************************************************************
 
1161
This must be called when a thread exits InnoDB in a lock wait or at the
 
1162
end of an SQL statement. */
 
1163
 
 
1164
void
 
1165
srv_conc_force_exit_innodb(
 
1166
/*=======================*/
 
1167
        trx_t*  trx)    /* in: transaction object associated with the
 
1168
                        thread */
 
1169
{
 
1170
        srv_conc_slot_t*        slot    = NULL;
 
1171
 
 
1172
        if (UNIV_LIKELY(!srv_thread_concurrency)) {
 
1173
 
 
1174
                return;
 
1175
        }
 
1176
 
 
1177
        if (trx->mysql_thd != NULL
 
1178
            && thd_is_replication_slave_thread(trx->mysql_thd)) {
 
1179
 
 
1180
                return;
 
1181
        }
 
1182
 
 
1183
        if (trx->declared_to_be_inside_innodb == FALSE) {
 
1184
 
 
1185
                return;
 
1186
        }
 
1187
 
 
1188
        os_fast_mutex_lock(&srv_conc_mutex);
 
1189
 
 
1190
        srv_conc_n_threads--;
 
1191
        trx->declared_to_be_inside_innodb = FALSE;
 
1192
        trx->n_tickets_to_enter_innodb = 0;
 
1193
 
 
1194
        if (srv_conc_n_threads < (lint)srv_thread_concurrency) {
 
1195
                /* Look for a slot where a thread is waiting and no other
 
1196
                thread has yet released the thread */
 
1197
 
 
1198
                slot = UT_LIST_GET_FIRST(srv_conc_queue);
 
1199
 
 
1200
                while (slot && slot->wait_ended == TRUE) {
 
1201
                        slot = UT_LIST_GET_NEXT(srv_conc_queue, slot);
 
1202
                }
 
1203
 
 
1204
                if (slot != NULL) {
 
1205
                        slot->wait_ended = TRUE;
 
1206
 
 
1207
                        /* We increment the count on behalf of the released
 
1208
                        thread */
 
1209
 
 
1210
                        srv_conc_n_threads++;
 
1211
                }
 
1212
        }
 
1213
 
 
1214
        os_fast_mutex_unlock(&srv_conc_mutex);
 
1215
 
 
1216
        if (slot != NULL) {
 
1217
                os_event_set(slot->event);
 
1218
        }
 
1219
}
 
1220
 
 
1221
/*************************************************************************
 
1222
This must be called when a thread exits InnoDB. */
 
1223
 
 
1224
void
 
1225
srv_conc_exit_innodb(
 
1226
/*=================*/
 
1227
        trx_t*  trx)    /* in: transaction object associated with the
 
1228
                        thread */
 
1229
{
 
1230
        if (trx->n_tickets_to_enter_innodb > 0) {
 
1231
                /* We will pretend the thread is still inside InnoDB though it
 
1232
                now leaves the InnoDB engine. In this way we save
 
1233
                a lot of semaphore operations. srv_conc_force_exit_innodb is
 
1234
                used to declare the thread definitely outside InnoDB. It
 
1235
                should be called when there is a lock wait or an SQL statement
 
1236
                ends. */
 
1237
 
 
1238
                return;
 
1239
        }
 
1240
 
 
1241
        srv_conc_force_exit_innodb(trx);
 
1242
}
 
1243
 
 
1244
/*========================================================================*/
 
1245
 
 
1246
/*************************************************************************
 
1247
Normalizes init parameter values to use units we use inside InnoDB. */
 
1248
static
 
1249
ulint
 
1250
srv_normalize_init_values(void)
 
1251
/*===========================*/
 
1252
                                /* out: DB_SUCCESS or error code */
 
1253
{
 
1254
        ulint   n;
 
1255
        ulint   i;
 
1256
 
 
1257
        n = srv_n_data_files;
 
1258
 
 
1259
        for (i = 0; i < n; i++) {
 
1260
                srv_data_file_sizes[i] = srv_data_file_sizes[i]
 
1261
                        * ((1024 * 1024) / UNIV_PAGE_SIZE);
 
1262
        }
 
1263
 
 
1264
        srv_last_file_size_max = srv_last_file_size_max
 
1265
                * ((1024 * 1024) / UNIV_PAGE_SIZE);
 
1266
 
 
1267
        srv_log_file_size = srv_log_file_size / UNIV_PAGE_SIZE;
 
1268
 
 
1269
        srv_log_buffer_size = srv_log_buffer_size / UNIV_PAGE_SIZE;
 
1270
 
 
1271
        srv_pool_size = srv_pool_size / (UNIV_PAGE_SIZE / 1024);
 
1272
 
 
1273
        srv_awe_window_size = srv_awe_window_size / UNIV_PAGE_SIZE;
 
1274
 
 
1275
        if (srv_use_awe) {
 
1276
                /* If we are using AWE we must save memory in the 32-bit
 
1277
                address space of the process, and cannot bind the lock
 
1278
                table size to the real buffer pool size. */
 
1279
 
 
1280
                srv_lock_table_size = 20 * srv_awe_window_size;
 
1281
        } else {
 
1282
                srv_lock_table_size = 5 * srv_pool_size;
 
1283
        }
 
1284
 
 
1285
        return(DB_SUCCESS);
 
1286
}
 
1287
 
 
1288
/*************************************************************************
 
1289
Boots the InnoDB server. */
 
1290
 
 
1291
ulint
 
1292
srv_boot(void)
 
1293
/*==========*/
 
1294
                        /* out: DB_SUCCESS or error code */
 
1295
{
 
1296
        ulint   err;
 
1297
 
 
1298
        /* Transform the init parameter values given by MySQL to
 
1299
        use units we use inside InnoDB: */
 
1300
 
 
1301
        err = srv_normalize_init_values();
 
1302
 
 
1303
        if (err != DB_SUCCESS) {
 
1304
                return(err);
 
1305
        }
 
1306
 
 
1307
        /* Initialize synchronization primitives, memory management, and thread
 
1308
        local storage */
 
1309
 
 
1310
        srv_general_init();
 
1311
 
 
1312
        /* Initialize this module */
 
1313
 
 
1314
        srv_init();
 
1315
 
 
1316
        return(DB_SUCCESS);
 
1317
}
 
1318
 
 
1319
#ifndef UNIV_HOTBACKUP
 
1320
/*************************************************************************
 
1321
Reserves a slot in the thread table for the current MySQL OS thread.
 
1322
NOTE! The kernel mutex has to be reserved by the caller! */
 
1323
static
 
1324
srv_slot_t*
 
1325
srv_table_reserve_slot_for_mysql(void)
 
1326
/*==================================*/
 
1327
                        /* out: reserved slot */
 
1328
{
 
1329
        srv_slot_t*     slot;
 
1330
        ulint           i;
 
1331
 
 
1332
        ut_ad(mutex_own(&kernel_mutex));
 
1333
 
 
1334
        i = 0;
 
1335
        slot = srv_mysql_table + i;
 
1336
 
 
1337
        while (slot->in_use) {
 
1338
                i++;
 
1339
 
 
1340
                if (i >= OS_THREAD_MAX_N) {
 
1341
 
 
1342
                        ut_print_timestamp(stderr);
 
1343
 
 
1344
                        fprintf(stderr,
 
1345
                                "  InnoDB: There appear to be %lu MySQL"
 
1346
                                " threads currently waiting\n"
 
1347
                                "InnoDB: inside InnoDB, which is the"
 
1348
                                " upper limit. Cannot continue operation.\n"
 
1349
                                "InnoDB: We intentionally generate"
 
1350
                                " a seg fault to print a stack trace\n"
 
1351
                                "InnoDB: on Linux. But first we print"
 
1352
                                " a list of waiting threads.\n", (ulong) i);
 
1353
 
 
1354
                        for (i = 0; i < OS_THREAD_MAX_N; i++) {
 
1355
 
 
1356
                                slot = srv_mysql_table + i;
 
1357
 
 
1358
                                fprintf(stderr,
 
1359
                                        "Slot %lu: thread id %lu, type %lu,"
 
1360
                                        " in use %lu, susp %lu, time %lu\n",
 
1361
                                        (ulong) i,
 
1362
                                        (ulong) os_thread_pf(slot->id),
 
1363
                                        (ulong) slot->type,
 
1364
                                        (ulong) slot->in_use,
 
1365
                                        (ulong) slot->suspended,
 
1366
                                        (ulong) difftime(ut_time(),
 
1367
                                                         slot->suspend_time));
 
1368
                        }
 
1369
 
 
1370
                        ut_error;
 
1371
                }
 
1372
 
 
1373
                slot = srv_mysql_table + i;
 
1374
        }
 
1375
 
 
1376
        ut_a(slot->in_use == FALSE);
 
1377
 
 
1378
        slot->in_use = TRUE;
 
1379
        slot->id = os_thread_get_curr_id();
 
1380
        slot->handle = os_thread_get_curr();
 
1381
 
 
1382
        return(slot);
 
1383
}
 
1384
#endif /* !UNIV_HOTBACKUP */
 
1385
 
 
1386
/*******************************************************************
 
1387
Puts a MySQL OS thread to wait for a lock to be released. If an error
 
1388
occurs during the wait trx->error_state associated with thr is
 
1389
!= DB_SUCCESS when we return. DB_LOCK_WAIT_TIMEOUT and DB_DEADLOCK
 
1390
are possible errors. DB_DEADLOCK is returned if selective deadlock
 
1391
resolution chose this transaction as a victim. */
 
1392
 
 
1393
void
 
1394
srv_suspend_mysql_thread(
 
1395
/*=====================*/
 
1396
        que_thr_t*      thr)    /* in: query thread associated with the MySQL
 
1397
                                OS thread */
 
1398
{
 
1399
#ifndef UNIV_HOTBACKUP
 
1400
        srv_slot_t*     slot;
 
1401
        os_event_t      event;
 
1402
        double          wait_time;
 
1403
        trx_t*          trx;
 
1404
        ibool           had_dict_lock                   = FALSE;
 
1405
        ibool           was_declared_inside_innodb      = FALSE;
 
1406
        ib_longlong     start_time                      = 0;
 
1407
        ib_longlong     finish_time;
 
1408
        ulint           diff_time;
 
1409
        ulint           sec;
 
1410
        ulint           ms;
 
1411
 
 
1412
        ut_ad(!mutex_own(&kernel_mutex));
 
1413
 
 
1414
        trx = thr_get_trx(thr);
 
1415
 
 
1416
        os_event_set(srv_lock_timeout_thread_event);
 
1417
 
 
1418
        mutex_enter(&kernel_mutex);
 
1419
 
 
1420
        trx->error_state = DB_SUCCESS;
 
1421
 
 
1422
        if (thr->state == QUE_THR_RUNNING) {
 
1423
 
 
1424
                ut_ad(thr->is_active == TRUE);
 
1425
 
 
1426
                /* The lock has already been released or this transaction
 
1427
                was chosen as a deadlock victim: no need to suspend */
 
1428
 
 
1429
                if (trx->was_chosen_as_deadlock_victim) {
 
1430
 
 
1431
                        trx->error_state = DB_DEADLOCK;
 
1432
                        trx->was_chosen_as_deadlock_victim = FALSE;
 
1433
                }
 
1434
 
 
1435
                mutex_exit(&kernel_mutex);
 
1436
 
 
1437
                return;
 
1438
        }
 
1439
 
 
1440
        ut_ad(thr->is_active == FALSE);
 
1441
 
 
1442
        slot = srv_table_reserve_slot_for_mysql();
 
1443
 
 
1444
        event = slot->event;
 
1445
 
 
1446
        slot->thr = thr;
 
1447
 
 
1448
        os_event_reset(event);
 
1449
 
 
1450
        slot->suspend_time = ut_time();
 
1451
 
 
1452
        if (thr->lock_state == QUE_THR_LOCK_ROW) {
 
1453
                srv_n_lock_wait_count++;
 
1454
                srv_n_lock_wait_current_count++;
 
1455
 
 
1456
                ut_usectime(&sec, &ms);
 
1457
                start_time = (ib_longlong)sec * 1000000 + ms;
 
1458
        }
 
1459
        /* Wake the lock timeout monitor thread, if it is suspended */
 
1460
 
 
1461
        os_event_set(srv_lock_timeout_thread_event);
 
1462
 
 
1463
        mutex_exit(&kernel_mutex);
 
1464
 
 
1465
        if (trx->declared_to_be_inside_innodb) {
 
1466
 
 
1467
                was_declared_inside_innodb = TRUE;
 
1468
 
 
1469
                /* We must declare this OS thread to exit InnoDB, since a
 
1470
                possible other thread holding a lock which this thread waits
 
1471
                for must be allowed to enter, sooner or later */
 
1472
 
 
1473
                srv_conc_force_exit_innodb(trx);
 
1474
        }
 
1475
 
 
1476
        /* Release possible foreign key check latch */
 
1477
        if (trx->dict_operation_lock_mode == RW_S_LATCH) {
 
1478
 
 
1479
                had_dict_lock = TRUE;
 
1480
 
 
1481
                row_mysql_unfreeze_data_dictionary(trx);
 
1482
        }
 
1483
 
 
1484
        ut_a(trx->dict_operation_lock_mode == 0);
 
1485
 
 
1486
        /* Wait for the release */
 
1487
 
 
1488
        os_event_wait(event);
 
1489
 
 
1490
        if (had_dict_lock) {
 
1491
 
 
1492
                row_mysql_freeze_data_dictionary(trx);
 
1493
        }
 
1494
 
 
1495
        if (was_declared_inside_innodb) {
 
1496
 
 
1497
                /* Return back inside InnoDB */
 
1498
 
 
1499
                srv_conc_force_enter_innodb(trx);
 
1500
        }
 
1501
 
 
1502
        mutex_enter(&kernel_mutex);
 
1503
 
 
1504
        /* Release the slot for others to use */
 
1505
 
 
1506
        slot->in_use = FALSE;
 
1507
 
 
1508
        wait_time = ut_difftime(ut_time(), slot->suspend_time);
 
1509
 
 
1510
        if (thr->lock_state == QUE_THR_LOCK_ROW) {
 
1511
                ut_usectime(&sec, &ms);
 
1512
                finish_time = (ib_longlong)sec * 1000000 + ms;
 
1513
 
 
1514
                diff_time = (ulint) (finish_time - start_time);
 
1515
 
 
1516
                srv_n_lock_wait_current_count--;
 
1517
                srv_n_lock_wait_time = srv_n_lock_wait_time + diff_time;
 
1518
                if (diff_time > srv_n_lock_max_wait_time) {
 
1519
                        srv_n_lock_max_wait_time = diff_time;
 
1520
                }
 
1521
        }
 
1522
 
 
1523
        if (trx->was_chosen_as_deadlock_victim) {
 
1524
 
 
1525
                trx->error_state = DB_DEADLOCK;
 
1526
                trx->was_chosen_as_deadlock_victim = FALSE;
 
1527
        }
 
1528
 
 
1529
        mutex_exit(&kernel_mutex);
 
1530
 
 
1531
        if (srv_lock_wait_timeout < 100000000
 
1532
            && wait_time > (double)srv_lock_wait_timeout) {
 
1533
 
 
1534
                trx->error_state = DB_LOCK_WAIT_TIMEOUT;
 
1535
        }
 
1536
#else /* UNIV_HOTBACKUP */
 
1537
        /* This function depends on MySQL code that is not included in
 
1538
        InnoDB Hot Backup builds.  Besides, this function should never
 
1539
        be called in InnoDB Hot Backup. */
 
1540
        ut_error;
 
1541
#endif /* UNIV_HOTBACKUP */
 
1542
}
 
1543
 
 
1544
/************************************************************************
 
1545
Releases a MySQL OS thread waiting for a lock to be released, if the
 
1546
thread is already suspended. */
 
1547
 
 
1548
void
 
1549
srv_release_mysql_thread_if_suspended(
 
1550
/*==================================*/
 
1551
        que_thr_t*      thr)    /* in: query thread associated with the
 
1552
                                MySQL OS thread  */
 
1553
{
 
1554
#ifndef UNIV_HOTBACKUP
 
1555
        srv_slot_t*     slot;
 
1556
        ulint           i;
 
1557
 
 
1558
        ut_ad(mutex_own(&kernel_mutex));
 
1559
 
 
1560
        for (i = 0; i < OS_THREAD_MAX_N; i++) {
 
1561
 
 
1562
                slot = srv_mysql_table + i;
 
1563
 
 
1564
                if (slot->in_use && slot->thr == thr) {
 
1565
                        /* Found */
 
1566
 
 
1567
                        os_event_set(slot->event);
 
1568
 
 
1569
                        return;
 
1570
                }
 
1571
        }
 
1572
 
 
1573
        /* not found */
 
1574
#else /* UNIV_HOTBACKUP */
 
1575
        /* This function depends on MySQL code that is not included in
 
1576
        InnoDB Hot Backup builds.  Besides, this function should never
 
1577
        be called in InnoDB Hot Backup. */
 
1578
        ut_error;
 
1579
#endif /* UNIV_HOTBACKUP */
 
1580
}
 
1581
 
 
1582
#ifndef UNIV_HOTBACKUP
 
1583
/**********************************************************************
 
1584
Refreshes the values used to calculate per-second averages. */
 
1585
static
 
1586
void
 
1587
srv_refresh_innodb_monitor_stats(void)
 
1588
/*==================================*/
 
1589
{
 
1590
        mutex_enter(&srv_innodb_monitor_mutex);
 
1591
 
 
1592
        srv_last_monitor_time = time(NULL);
 
1593
 
 
1594
        os_aio_refresh_stats();
 
1595
 
 
1596
        btr_cur_n_sea_old = btr_cur_n_sea;
 
1597
        btr_cur_n_non_sea_old = btr_cur_n_non_sea;
 
1598
 
 
1599
        log_refresh_stats();
 
1600
 
 
1601
        buf_refresh_io_stats();
 
1602
 
 
1603
        srv_n_rows_inserted_old = srv_n_rows_inserted;
 
1604
        srv_n_rows_updated_old = srv_n_rows_updated;
 
1605
        srv_n_rows_deleted_old = srv_n_rows_deleted;
 
1606
        srv_n_rows_read_old = srv_n_rows_read;
 
1607
 
 
1608
        mutex_exit(&srv_innodb_monitor_mutex);
 
1609
}
 
1610
 
 
1611
/**********************************************************************
 
1612
Outputs to a file the output of the InnoDB Monitor. */
 
1613
 
 
1614
void
 
1615
srv_printf_innodb_monitor(
 
1616
/*======================*/
 
1617
        FILE*   file,           /* in: output stream */
 
1618
        ulint*  trx_start,      /* out: file position of the start of
 
1619
                                the list of active transactions */
 
1620
        ulint*  trx_end)        /* out: file position of the end of
 
1621
                                the list of active transactions */
 
1622
{
 
1623
        double  time_elapsed;
 
1624
        time_t  current_time;
 
1625
        ulint   n_reserved;
 
1626
 
 
1627
        mutex_enter(&srv_innodb_monitor_mutex);
 
1628
 
 
1629
        current_time = time(NULL);
 
1630
 
 
1631
        /* We add 0.001 seconds to time_elapsed to prevent division
 
1632
        by zero if two users happen to call SHOW INNODB STATUS at the same
 
1633
        time */
 
1634
 
 
1635
        time_elapsed = difftime(current_time, srv_last_monitor_time)
 
1636
                + 0.001;
 
1637
 
 
1638
        srv_last_monitor_time = time(NULL);
 
1639
 
 
1640
        fputs("\n=====================================\n", file);
 
1641
 
 
1642
        ut_print_timestamp(file);
 
1643
        fprintf(file,
 
1644
                " INNODB MONITOR OUTPUT\n"
 
1645
                "=====================================\n"
 
1646
                "Per second averages calculated from the last %lu seconds\n",
 
1647
                (ulong)time_elapsed);
 
1648
 
 
1649
        fputs("----------\n"
 
1650
              "SEMAPHORES\n"
 
1651
              "----------\n", file);
 
1652
        sync_print(file);
 
1653
 
 
1654
        /* Conceptually, srv_innodb_monitor_mutex has a very high latching
 
1655
        order level in sync0sync.h, while dict_foreign_err_mutex has a very
 
1656
        low level 135. Therefore we can reserve the latter mutex here without
 
1657
        a danger of a deadlock of threads. */
 
1658
 
 
1659
        mutex_enter(&dict_foreign_err_mutex);
 
1660
 
 
1661
        if (ftell(dict_foreign_err_file) != 0L) {
 
1662
                fputs("------------------------\n"
 
1663
                      "LATEST FOREIGN KEY ERROR\n"
 
1664
                      "------------------------\n", file);
 
1665
                ut_copy_file(file, dict_foreign_err_file);
 
1666
        }
 
1667
 
 
1668
        mutex_exit(&dict_foreign_err_mutex);
 
1669
 
 
1670
        lock_print_info_summary(file);
 
1671
        if (trx_start) {
 
1672
                long    t = ftell(file);
 
1673
                if (t < 0) {
 
1674
                        *trx_start = ULINT_UNDEFINED;
 
1675
                } else {
 
1676
                        *trx_start = (ulint) t;
 
1677
                }
 
1678
        }
 
1679
        lock_print_info_all_transactions(file);
 
1680
        if (trx_end) {
 
1681
                long    t = ftell(file);
 
1682
                if (t < 0) {
 
1683
                        *trx_end = ULINT_UNDEFINED;
 
1684
                } else {
 
1685
                        *trx_end = (ulint) t;
 
1686
                }
 
1687
        }
 
1688
        fputs("--------\n"
 
1689
              "FILE I/O\n"
 
1690
              "--------\n", file);
 
1691
        os_aio_print(file);
 
1692
 
 
1693
        fputs("-------------------------------------\n"
 
1694
              "INSERT BUFFER AND ADAPTIVE HASH INDEX\n"
 
1695
              "-------------------------------------\n", file);
 
1696
        ibuf_print(file);
 
1697
 
 
1698
        ha_print_info(file, btr_search_sys->hash_index);
 
1699
 
 
1700
        fprintf(file,
 
1701
                "%.2f hash searches/s, %.2f non-hash searches/s\n",
 
1702
                (btr_cur_n_sea - btr_cur_n_sea_old)
 
1703
                / time_elapsed,
 
1704
                (btr_cur_n_non_sea - btr_cur_n_non_sea_old)
 
1705
                / time_elapsed);
 
1706
        btr_cur_n_sea_old = btr_cur_n_sea;
 
1707
        btr_cur_n_non_sea_old = btr_cur_n_non_sea;
 
1708
 
 
1709
        fputs("---\n"
 
1710
              "LOG\n"
 
1711
              "---\n", file);
 
1712
        log_print(file);
 
1713
 
 
1714
        fputs("----------------------\n"
 
1715
              "BUFFER POOL AND MEMORY\n"
 
1716
              "----------------------\n", file);
 
1717
        fprintf(file,
 
1718
                "Total memory allocated " ULINTPF
 
1719
                "; in additional pool allocated " ULINTPF "\n",
 
1720
                ut_total_allocated_memory,
 
1721
                mem_pool_get_reserved(mem_comm_pool));
 
1722
        fprintf(file, "Dictionary memory allocated " ULINTPF "\n",
 
1723
                dict_sys->size);
 
1724
 
 
1725
        if (srv_use_awe) {
 
1726
                fprintf(file,
 
1727
                        "In addition to that %lu MB of AWE memory allocated\n",
 
1728
                        (ulong) (srv_pool_size
 
1729
                                 / ((1024 * 1024) / UNIV_PAGE_SIZE)));
 
1730
        }
 
1731
 
 
1732
        buf_print_io(file);
 
1733
 
 
1734
        fputs("--------------\n"
 
1735
              "ROW OPERATIONS\n"
 
1736
              "--------------\n", file);
 
1737
        fprintf(file, "%ld queries inside InnoDB, %lu queries in queue\n",
 
1738
                (long) srv_conc_n_threads,
 
1739
                (ulong) srv_conc_n_waiting_threads);
 
1740
 
 
1741
        fprintf(file, "%lu read views open inside InnoDB\n",
 
1742
                UT_LIST_GET_LEN(trx_sys->view_list));
 
1743
 
 
1744
        n_reserved = fil_space_get_n_reserved_extents(0);
 
1745
        if (n_reserved > 0) {
 
1746
                fprintf(file,
 
1747
                        "%lu tablespace extents now reserved for"
 
1748
                        " B-tree split operations\n",
 
1749
                        (ulong) n_reserved);
 
1750
        }
 
1751
 
 
1752
#ifdef UNIV_LINUX
 
1753
        fprintf(file, "Main thread process no. %lu, id %lu, state: %s\n",
 
1754
                (ulong) srv_main_thread_process_no,
 
1755
                (ulong) srv_main_thread_id,
 
1756
                srv_main_thread_op_info);
 
1757
#else
 
1758
        fprintf(file, "Main thread id %lu, state: %s\n",
 
1759
                (ulong) srv_main_thread_id,
 
1760
                srv_main_thread_op_info);
 
1761
#endif
 
1762
        fprintf(file,
 
1763
                "Number of rows inserted " ULINTPF
 
1764
                ", updated " ULINTPF ", deleted " ULINTPF
 
1765
                ", read " ULINTPF "\n",
 
1766
                srv_n_rows_inserted,
 
1767
                srv_n_rows_updated,
 
1768
                srv_n_rows_deleted,
 
1769
                srv_n_rows_read);
 
1770
        fprintf(file,
 
1771
                "%.2f inserts/s, %.2f updates/s,"
 
1772
                " %.2f deletes/s, %.2f reads/s\n",
 
1773
                (srv_n_rows_inserted - srv_n_rows_inserted_old)
 
1774
                / time_elapsed,
 
1775
                (srv_n_rows_updated - srv_n_rows_updated_old)
 
1776
                / time_elapsed,
 
1777
                (srv_n_rows_deleted - srv_n_rows_deleted_old)
 
1778
                / time_elapsed,
 
1779
                (srv_n_rows_read - srv_n_rows_read_old)
 
1780
                / time_elapsed);
 
1781
 
 
1782
        srv_n_rows_inserted_old = srv_n_rows_inserted;
 
1783
        srv_n_rows_updated_old = srv_n_rows_updated;
 
1784
        srv_n_rows_deleted_old = srv_n_rows_deleted;
 
1785
        srv_n_rows_read_old = srv_n_rows_read;
 
1786
 
 
1787
        fputs("----------------------------\n"
 
1788
              "END OF INNODB MONITOR OUTPUT\n"
 
1789
              "============================\n", file);
 
1790
        mutex_exit(&srv_innodb_monitor_mutex);
 
1791
        fflush(file);
 
1792
}
 
1793
 
 
1794
/**********************************************************************
 
1795
Function to pass InnoDB status variables to MySQL */
 
1796
 
 
1797
void
 
1798
srv_export_innodb_status(void)
 
1799
{
 
1800
        mutex_enter(&srv_innodb_monitor_mutex);
 
1801
 
 
1802
        export_vars.innodb_data_pending_reads
 
1803
                = os_n_pending_reads;
 
1804
        export_vars.innodb_data_pending_writes
 
1805
                = os_n_pending_writes;
 
1806
        export_vars.innodb_data_pending_fsyncs
 
1807
                = fil_n_pending_log_flushes
 
1808
                + fil_n_pending_tablespace_flushes;
 
1809
        export_vars.innodb_data_fsyncs = os_n_fsyncs;
 
1810
        export_vars.innodb_data_read = srv_data_read;
 
1811
        export_vars.innodb_data_reads = os_n_file_reads;
 
1812
        export_vars.innodb_data_writes = os_n_file_writes;
 
1813
        export_vars.innodb_data_written = srv_data_written;
 
1814
        export_vars.innodb_buffer_pool_read_requests = buf_pool->n_page_gets;
 
1815
        export_vars.innodb_buffer_pool_write_requests
 
1816
                = srv_buf_pool_write_requests;
 
1817
        export_vars.innodb_buffer_pool_wait_free = srv_buf_pool_wait_free;
 
1818
        export_vars.innodb_buffer_pool_pages_flushed = srv_buf_pool_flushed;
 
1819
        export_vars.innodb_buffer_pool_reads = srv_buf_pool_reads;
 
1820
        export_vars.innodb_buffer_pool_read_ahead_rnd = srv_read_ahead_rnd;
 
1821
        export_vars.innodb_buffer_pool_read_ahead_seq = srv_read_ahead_seq;
 
1822
        export_vars.innodb_buffer_pool_pages_data
 
1823
                = UT_LIST_GET_LEN(buf_pool->LRU);
 
1824
        export_vars.innodb_buffer_pool_pages_dirty
 
1825
                = UT_LIST_GET_LEN(buf_pool->flush_list);
 
1826
        export_vars.innodb_buffer_pool_pages_free
 
1827
                = UT_LIST_GET_LEN(buf_pool->free);
 
1828
        export_vars.innodb_buffer_pool_pages_latched
 
1829
                = buf_get_latched_pages_number();
 
1830
        export_vars.innodb_buffer_pool_pages_total = buf_pool->curr_size;
 
1831
 
 
1832
        export_vars.innodb_buffer_pool_pages_misc = buf_pool->max_size
 
1833
                - UT_LIST_GET_LEN(buf_pool->LRU)
 
1834
                - UT_LIST_GET_LEN(buf_pool->free);
 
1835
        export_vars.innodb_page_size = UNIV_PAGE_SIZE;
 
1836
        export_vars.innodb_log_waits = srv_log_waits;
 
1837
        export_vars.innodb_os_log_written = srv_os_log_written;
 
1838
        export_vars.innodb_os_log_fsyncs = fil_n_log_flushes;
 
1839
        export_vars.innodb_os_log_pending_fsyncs = fil_n_pending_log_flushes;
 
1840
        export_vars.innodb_os_log_pending_writes = srv_os_log_pending_writes;
 
1841
        export_vars.innodb_log_write_requests = srv_log_write_requests;
 
1842
        export_vars.innodb_log_writes = srv_log_writes;
 
1843
        export_vars.innodb_dblwr_pages_written = srv_dblwr_pages_written;
 
1844
        export_vars.innodb_dblwr_writes = srv_dblwr_writes;
 
1845
        export_vars.innodb_pages_created = buf_pool->n_pages_created;
 
1846
        export_vars.innodb_pages_read = buf_pool->n_pages_read;
 
1847
        export_vars.innodb_pages_written = buf_pool->n_pages_written;
 
1848
        export_vars.innodb_row_lock_waits = srv_n_lock_wait_count;
 
1849
        export_vars.innodb_row_lock_current_waits
 
1850
                = srv_n_lock_wait_current_count;
 
1851
        export_vars.innodb_row_lock_time = srv_n_lock_wait_time / 1000;
 
1852
        if (srv_n_lock_wait_count > 0) {
 
1853
                export_vars.innodb_row_lock_time_avg = (ulint)
 
1854
                        (srv_n_lock_wait_time / 1000 / srv_n_lock_wait_count);
 
1855
        } else {
 
1856
                export_vars.innodb_row_lock_time_avg = 0;
 
1857
        }
 
1858
        export_vars.innodb_row_lock_time_max
 
1859
                = srv_n_lock_max_wait_time / 1000;
 
1860
        export_vars.innodb_rows_read = srv_n_rows_read;
 
1861
        export_vars.innodb_rows_inserted = srv_n_rows_inserted;
 
1862
        export_vars.innodb_rows_updated = srv_n_rows_updated;
 
1863
        export_vars.innodb_rows_deleted = srv_n_rows_deleted;
 
1864
 
 
1865
        mutex_exit(&srv_innodb_monitor_mutex);
 
1866
}
 
1867
 
 
1868
/*************************************************************************
 
1869
A thread which wakes up threads whose lock wait may have lasted too long.
 
1870
This also prints the info output by various InnoDB monitors. */
 
1871
 
 
1872
os_thread_ret_t
 
1873
srv_lock_timeout_and_monitor_thread(
 
1874
/*================================*/
 
1875
                        /* out: a dummy parameter */
 
1876
        void*   arg __attribute__((unused)))
 
1877
                        /* in: a dummy parameter required by
 
1878
                        os_thread_create */
 
1879
{
 
1880
        srv_slot_t*     slot;
 
1881
        double          time_elapsed;
 
1882
        time_t          current_time;
 
1883
        time_t          last_table_monitor_time;
 
1884
        time_t          last_tablespace_monitor_time;
 
1885
        time_t          last_monitor_time;
 
1886
        ibool           some_waits;
 
1887
        double          wait_time;
 
1888
        ulint           i;
 
1889
 
 
1890
#ifdef UNIV_DEBUG_THREAD_CREATION
 
1891
        fprintf(stderr, "Lock timeout thread starts, id %lu\n",
 
1892
                os_thread_pf(os_thread_get_curr_id()));
 
1893
#endif
 
1894
        UT_NOT_USED(arg);
 
1895
        srv_last_monitor_time = time(NULL);
 
1896
        last_table_monitor_time = time(NULL);
 
1897
        last_tablespace_monitor_time = time(NULL);
 
1898
        last_monitor_time = time(NULL);
 
1899
loop:
 
1900
        srv_lock_timeout_and_monitor_active = TRUE;
 
1901
 
 
1902
        /* When someone is waiting for a lock, we wake up every second
 
1903
        and check if a timeout has passed for a lock wait */
 
1904
 
 
1905
        os_thread_sleep(1000000);
 
1906
 
 
1907
        /* In case mutex_exit is not a memory barrier, it is
 
1908
        theoretically possible some threads are left waiting though
 
1909
        the semaphore is already released. Wake up those threads: */
 
1910
 
 
1911
        sync_arr_wake_threads_if_sema_free();
 
1912
 
 
1913
        current_time = time(NULL);
 
1914
 
 
1915
        time_elapsed = difftime(current_time, last_monitor_time);
 
1916
 
 
1917
        if (time_elapsed > 15) {
 
1918
                last_monitor_time = time(NULL);
 
1919
 
 
1920
                if (srv_print_innodb_monitor) {
 
1921
                        srv_printf_innodb_monitor(stderr, NULL, NULL);
 
1922
                }
 
1923
 
 
1924
                if (srv_innodb_status) {
 
1925
                        mutex_enter(&srv_monitor_file_mutex);
 
1926
                        rewind(srv_monitor_file);
 
1927
                        srv_printf_innodb_monitor(srv_monitor_file, NULL,
 
1928
                                                  NULL);
 
1929
                        os_file_set_eof(srv_monitor_file);
 
1930
                        mutex_exit(&srv_monitor_file_mutex);
 
1931
                }
 
1932
 
 
1933
                if (srv_print_innodb_tablespace_monitor
 
1934
                    && difftime(current_time,
 
1935
                                last_tablespace_monitor_time) > 60) {
 
1936
                        last_tablespace_monitor_time = time(NULL);
 
1937
 
 
1938
                        fputs("========================"
 
1939
                              "========================\n",
 
1940
                              stderr);
 
1941
 
 
1942
                        ut_print_timestamp(stderr);
 
1943
 
 
1944
                        fputs(" INNODB TABLESPACE MONITOR OUTPUT\n"
 
1945
                              "========================"
 
1946
                              "========================\n",
 
1947
                              stderr);
 
1948
 
 
1949
                        fsp_print(0);
 
1950
                        fputs("Validating tablespace\n", stderr);
 
1951
                        fsp_validate(0);
 
1952
                        fputs("Validation ok\n"
 
1953
                              "---------------------------------------\n"
 
1954
                              "END OF INNODB TABLESPACE MONITOR OUTPUT\n"
 
1955
                              "=======================================\n",
 
1956
                              stderr);
 
1957
                }
 
1958
 
 
1959
                if (srv_print_innodb_table_monitor
 
1960
                    && difftime(current_time, last_table_monitor_time) > 60) {
 
1961
 
 
1962
                        last_table_monitor_time = time(NULL);
 
1963
 
 
1964
                        fputs("===========================================\n",
 
1965
                              stderr);
 
1966
 
 
1967
                        ut_print_timestamp(stderr);
 
1968
 
 
1969
                        fputs(" INNODB TABLE MONITOR OUTPUT\n"
 
1970
                              "===========================================\n",
 
1971
                              stderr);
 
1972
                        dict_print();
 
1973
 
 
1974
                        fputs("-----------------------------------\n"
 
1975
                              "END OF INNODB TABLE MONITOR OUTPUT\n"
 
1976
                              "==================================\n",
 
1977
                              stderr);
 
1978
                }
 
1979
        }
 
1980
 
 
1981
        mutex_enter(&kernel_mutex);
 
1982
 
 
1983
        some_waits = FALSE;
 
1984
 
 
1985
        /* Check of all slots if a thread is waiting there, and if it
 
1986
        has exceeded the time limit */
 
1987
 
 
1988
        for (i = 0; i < OS_THREAD_MAX_N; i++) {
 
1989
 
 
1990
                slot = srv_mysql_table + i;
 
1991
 
 
1992
                if (slot->in_use) {
 
1993
                        some_waits = TRUE;
 
1994
 
 
1995
                        wait_time = ut_difftime(ut_time(), slot->suspend_time);
 
1996
 
 
1997
                        if (srv_lock_wait_timeout < 100000000
 
1998
                            && (wait_time > (double) srv_lock_wait_timeout
 
1999
                                || wait_time < 0)) {
 
2000
 
 
2001
                                /* Timeout exceeded or a wrap-around in system
 
2002
                                time counter: cancel the lock request queued
 
2003
                                by the transaction and release possible
 
2004
                                other transactions waiting behind; it is
 
2005
                                possible that the lock has already been
 
2006
                                granted: in that case do nothing */
 
2007
 
 
2008
                                if (thr_get_trx(slot->thr)->wait_lock) {
 
2009
                                        lock_cancel_waiting_and_release(
 
2010
                                                thr_get_trx(slot->thr)
 
2011
                                                ->wait_lock);
 
2012
                                }
 
2013
                        }
 
2014
                }
 
2015
        }
 
2016
 
 
2017
        os_event_reset(srv_lock_timeout_thread_event);
 
2018
 
 
2019
        mutex_exit(&kernel_mutex);
 
2020
 
 
2021
        if (srv_shutdown_state >= SRV_SHUTDOWN_CLEANUP) {
 
2022
                goto exit_func;
 
2023
        }
 
2024
 
 
2025
        if (some_waits || srv_print_innodb_monitor
 
2026
            || srv_print_innodb_lock_monitor
 
2027
            || srv_print_innodb_tablespace_monitor
 
2028
            || srv_print_innodb_table_monitor) {
 
2029
                goto loop;
 
2030
        }
 
2031
 
 
2032
        /* No one was waiting for a lock and no monitor was active:
 
2033
        suspend this thread */
 
2034
 
 
2035
        srv_lock_timeout_and_monitor_active = FALSE;
 
2036
 
 
2037
#if 0
 
2038
        /* The following synchronisation is disabled, since
 
2039
        the InnoDB monitor output is to be updated every 15 seconds. */
 
2040
        os_event_wait(srv_lock_timeout_thread_event);
 
2041
#endif
 
2042
        goto loop;
 
2043
 
 
2044
exit_func:
 
2045
        srv_lock_timeout_and_monitor_active = FALSE;
 
2046
 
 
2047
        /* We count the number of threads in os_thread_exit(). A created
 
2048
        thread should always use that to exit and not use return() to exit. */
 
2049
 
 
2050
        os_thread_exit(NULL);
 
2051
 
 
2052
        OS_THREAD_DUMMY_RETURN;
 
2053
}
 
2054
 
 
2055
/*************************************************************************
 
2056
A thread which prints warnings about semaphore waits which have lasted
 
2057
too long. These can be used to track bugs which cause hangs. */
 
2058
 
 
2059
os_thread_ret_t
 
2060
srv_error_monitor_thread(
 
2061
/*=====================*/
 
2062
                        /* out: a dummy parameter */
 
2063
        void*   arg __attribute__((unused)))
 
2064
                        /* in: a dummy parameter required by
 
2065
                        os_thread_create */
 
2066
{
 
2067
        /* number of successive fatal timeouts observed */
 
2068
        ulint   fatal_cnt       = 0;
 
2069
        dulint  old_lsn;
 
2070
        dulint  new_lsn;
 
2071
 
 
2072
        old_lsn = srv_start_lsn;
 
2073
 
 
2074
#ifdef UNIV_DEBUG_THREAD_CREATION
 
2075
        fprintf(stderr, "Error monitor thread starts, id %lu\n",
 
2076
                os_thread_pf(os_thread_get_curr_id()));
 
2077
#endif
 
2078
loop:
 
2079
        srv_error_monitor_active = TRUE;
 
2080
 
 
2081
        /* Try to track a strange bug reported by Harald Fuchs and others,
 
2082
        where the lsn seems to decrease at times */
 
2083
 
 
2084
        new_lsn = log_get_lsn();
 
2085
 
 
2086
        if (ut_dulint_cmp(new_lsn, old_lsn) < 0) {
 
2087
                ut_print_timestamp(stderr);
 
2088
                fprintf(stderr,
 
2089
                        "  InnoDB: Error: old log sequence number %lu %lu"
 
2090
                        " was greater\n"
 
2091
                        "InnoDB: than the new log sequence number %lu %lu!\n"
 
2092
                        "InnoDB: Please submit a bug report"
 
2093
                        " to http://bugs.mysql.com\n",
 
2094
                        (ulong) ut_dulint_get_high(old_lsn),
 
2095
                        (ulong) ut_dulint_get_low(old_lsn),
 
2096
                        (ulong) ut_dulint_get_high(new_lsn),
 
2097
                        (ulong) ut_dulint_get_low(new_lsn));
 
2098
        }
 
2099
 
 
2100
        old_lsn = new_lsn;
 
2101
 
 
2102
        if (difftime(time(NULL), srv_last_monitor_time) > 60) {
 
2103
                /* We referesh InnoDB Monitor values so that averages are
 
2104
                printed from at most 60 last seconds */
 
2105
 
 
2106
                srv_refresh_innodb_monitor_stats();
 
2107
        }
 
2108
 
 
2109
        if (sync_array_print_long_waits()) {
 
2110
                fatal_cnt++;
 
2111
                if (fatal_cnt > 5) {
 
2112
 
 
2113
                        fprintf(stderr,
 
2114
                                "InnoDB: Error: semaphore wait has lasted"
 
2115
                                " > %lu seconds\n"
 
2116
                                "InnoDB: We intentionally crash the server,"
 
2117
                                " because it appears to be hung.\n",
 
2118
                                (ulong) srv_fatal_semaphore_wait_threshold);
 
2119
 
 
2120
                        ut_error;
 
2121
                }
 
2122
        } else {
 
2123
                fatal_cnt = 0;
 
2124
        }
 
2125
 
 
2126
        /* Flush stderr so that a database user gets the output
 
2127
        to possible MySQL error file */
 
2128
 
 
2129
        fflush(stderr);
 
2130
 
 
2131
        os_thread_sleep(2000000);
 
2132
 
 
2133
        if (srv_shutdown_state < SRV_SHUTDOWN_CLEANUP) {
 
2134
 
 
2135
                goto loop;
 
2136
        }
 
2137
 
 
2138
        srv_error_monitor_active = FALSE;
 
2139
 
 
2140
        /* We count the number of threads in os_thread_exit(). A created
 
2141
        thread should always use that to exit and not use return() to exit. */
 
2142
 
 
2143
        os_thread_exit(NULL);
 
2144
 
 
2145
        OS_THREAD_DUMMY_RETURN;
 
2146
}
 
2147
 
 
2148
/***********************************************************************
 
2149
Tells the InnoDB server that there has been activity in the database
 
2150
and wakes up the master thread if it is suspended (not sleeping). Used
 
2151
in the MySQL interface. Note that there is a small chance that the master
 
2152
thread stays suspended (we do not protect our operation with the kernel
 
2153
mutex, for performace reasons). */
 
2154
 
 
2155
void
 
2156
srv_active_wake_master_thread(void)
 
2157
/*===============================*/
 
2158
{
 
2159
        srv_activity_count++;
 
2160
 
 
2161
        if (srv_n_threads_active[SRV_MASTER] == 0) {
 
2162
 
 
2163
                mutex_enter(&kernel_mutex);
 
2164
 
 
2165
                srv_release_threads(SRV_MASTER, 1);
 
2166
 
 
2167
                mutex_exit(&kernel_mutex);
 
2168
        }
 
2169
}
 
2170
 
 
2171
/***********************************************************************
 
2172
Wakes up the master thread if it is suspended or being suspended. */
 
2173
 
 
2174
void
 
2175
srv_wake_master_thread(void)
 
2176
/*========================*/
 
2177
{
 
2178
        srv_activity_count++;
 
2179
 
 
2180
        mutex_enter(&kernel_mutex);
 
2181
 
 
2182
        srv_release_threads(SRV_MASTER, 1);
 
2183
 
 
2184
        mutex_exit(&kernel_mutex);
 
2185
}
 
2186
 
 
2187
/*************************************************************************
 
2188
The master thread controlling the server. */
 
2189
 
 
2190
os_thread_ret_t
 
2191
srv_master_thread(
 
2192
/*==============*/
 
2193
                        /* out: a dummy parameter */
 
2194
        void*   arg __attribute__((unused)))
 
2195
                        /* in: a dummy parameter required by
 
2196
                        os_thread_create */
 
2197
{
 
2198
        os_event_t      event;
 
2199
        time_t          last_flush_time;
 
2200
        time_t          current_time;
 
2201
        ulint           old_activity_count;
 
2202
        ulint           n_pages_purged;
 
2203
        ulint           n_bytes_merged;
 
2204
        ulint           n_pages_flushed;
 
2205
        ulint           n_bytes_archived;
 
2206
        ulint           n_tables_to_drop;
 
2207
        ulint           n_ios;
 
2208
        ulint           n_ios_old;
 
2209
        ulint           n_ios_very_old;
 
2210
        ulint           n_pend_ios;
 
2211
        ibool           skip_sleep      = FALSE;
 
2212
        ulint           i;
 
2213
 
 
2214
#ifdef UNIV_DEBUG_THREAD_CREATION
 
2215
        fprintf(stderr, "Master thread starts, id %lu\n",
 
2216
                os_thread_pf(os_thread_get_curr_id()));
 
2217
#endif
 
2218
        srv_main_thread_process_no = os_proc_get_number();
 
2219
        srv_main_thread_id = os_thread_pf(os_thread_get_curr_id());
 
2220
 
 
2221
        srv_table_reserve_slot(SRV_MASTER);
 
2222
 
 
2223
        mutex_enter(&kernel_mutex);
 
2224
 
 
2225
        srv_n_threads_active[SRV_MASTER]++;
 
2226
 
 
2227
        mutex_exit(&kernel_mutex);
 
2228
 
 
2229
loop:
 
2230
        /*****************************************************************/
 
2231
        /* ---- When there is database activity by users, we cycle in this
 
2232
        loop */
 
2233
 
 
2234
        srv_main_thread_op_info = "reserving kernel mutex";
 
2235
 
 
2236
        n_ios_very_old = log_sys->n_log_ios + buf_pool->n_pages_read
 
2237
                + buf_pool->n_pages_written;
 
2238
        mutex_enter(&kernel_mutex);
 
2239
 
 
2240
        /* Store the user activity counter at the start of this loop */
 
2241
        old_activity_count = srv_activity_count;
 
2242
 
 
2243
        mutex_exit(&kernel_mutex);
 
2244
 
 
2245
        if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) {
 
2246
 
 
2247
                goto suspend_thread;
 
2248
        }
 
2249
 
 
2250
        /* ---- We run the following loop approximately once per second
 
2251
        when there is database activity */
 
2252
 
 
2253
        skip_sleep = FALSE;
 
2254
 
 
2255
        for (i = 0; i < 10; i++) {
 
2256
                n_ios_old = log_sys->n_log_ios + buf_pool->n_pages_read
 
2257
                        + buf_pool->n_pages_written;
 
2258
                srv_main_thread_op_info = "sleeping";
 
2259
 
 
2260
                if (!skip_sleep) {
 
2261
 
 
2262
                        os_thread_sleep(1000000);
 
2263
                }
 
2264
 
 
2265
                skip_sleep = FALSE;
 
2266
 
 
2267
                /* ALTER TABLE in MySQL requires on Unix that the table handler
 
2268
                can drop tables lazily after there no longer are SELECT
 
2269
                queries to them. */
 
2270
 
 
2271
                srv_main_thread_op_info = "doing background drop tables";
 
2272
 
 
2273
                row_drop_tables_for_mysql_in_background();
 
2274
 
 
2275
                srv_main_thread_op_info = "";
 
2276
 
 
2277
                if (srv_fast_shutdown && srv_shutdown_state > 0) {
 
2278
 
 
2279
                        goto background_loop;
 
2280
                }
 
2281
 
 
2282
                /* We flush the log once in a second even if no commit
 
2283
                is issued or the we have specified in my.cnf no flush
 
2284
                at transaction commit */
 
2285
 
 
2286
                srv_main_thread_op_info = "flushing log";
 
2287
                log_buffer_flush_to_disk();
 
2288
 
 
2289
                srv_main_thread_op_info = "making checkpoint";
 
2290
                log_free_check();
 
2291
 
 
2292
                /* If there were less than 5 i/os during the
 
2293
                one second sleep, we assume that there is free
 
2294
                disk i/o capacity available, and it makes sense to
 
2295
                do an insert buffer merge. */
 
2296
 
 
2297
                n_pend_ios = buf_get_n_pending_ios()
 
2298
                        + log_sys->n_pending_writes;
 
2299
                n_ios = log_sys->n_log_ios + buf_pool->n_pages_read
 
2300
                        + buf_pool->n_pages_written;
 
2301
                if (n_pend_ios < 3 && (n_ios - n_ios_old < 5)) {
 
2302
                        srv_main_thread_op_info = "doing insert buffer merge";
 
2303
                        ibuf_contract_for_n_pages(
 
2304
                                TRUE, srv_insert_buffer_batch_size / 4);
 
2305
 
 
2306
                        srv_main_thread_op_info = "flushing log";
 
2307
 
 
2308
                        log_buffer_flush_to_disk();
 
2309
                }
 
2310
 
 
2311
                if (UNIV_UNLIKELY(buf_get_modified_ratio_pct()
 
2312
                                  > srv_max_buf_pool_modified_pct)) {
 
2313
 
 
2314
                        /* Try to keep the number of modified pages in the
 
2315
                        buffer pool under the limit wished by the user */
 
2316
 
 
2317
                        n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100,
 
2318
                                                          ut_dulint_max);
 
2319
 
 
2320
                        /* If we had to do the flush, it may have taken
 
2321
                        even more than 1 second, and also, there may be more
 
2322
                        to flush. Do not sleep 1 second during the next
 
2323
                        iteration of this loop. */
 
2324
 
 
2325
                        skip_sleep = TRUE;
 
2326
                }
 
2327
 
 
2328
                if (srv_activity_count == old_activity_count) {
 
2329
 
 
2330
                        /* There is no user activity at the moment, go to
 
2331
                        the background loop */
 
2332
 
 
2333
                        goto background_loop;
 
2334
                }
 
2335
        }
 
2336
 
 
2337
        /* ---- We perform the following code approximately once per
 
2338
        10 seconds when there is database activity */
 
2339
 
 
2340
#ifdef MEM_PERIODIC_CHECK
 
2341
        /* Check magic numbers of every allocated mem block once in 10
 
2342
        seconds */
 
2343
        mem_validate_all_blocks();
 
2344
#endif
 
2345
        /* If there were less than 200 i/os during the 10 second period,
 
2346
        we assume that there is free disk i/o capacity available, and it
 
2347
        makes sense to flush 100 pages. */
 
2348
 
 
2349
        n_pend_ios = buf_get_n_pending_ios() + log_sys->n_pending_writes;
 
2350
        n_ios = log_sys->n_log_ios + buf_pool->n_pages_read
 
2351
                + buf_pool->n_pages_written;
 
2352
        if (n_pend_ios < 3 && (n_ios - n_ios_very_old < 200)) {
 
2353
 
 
2354
                srv_main_thread_op_info = "flushing buffer pool pages";
 
2355
                buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max);
 
2356
 
 
2357
                srv_main_thread_op_info = "flushing log";
 
2358
                log_buffer_flush_to_disk();
 
2359
        }
 
2360
 
 
2361
        /* We run a batch of insert buffer merge every 10 seconds,
 
2362
        even if the server were active */
 
2363
 
 
2364
        srv_main_thread_op_info = "doing insert buffer merge";
 
2365
        ibuf_contract_for_n_pages(TRUE, srv_insert_buffer_batch_size / 4);
 
2366
 
 
2367
        srv_main_thread_op_info = "flushing log";
 
2368
        log_buffer_flush_to_disk();
 
2369
 
 
2370
        /* We run a full purge every 10 seconds, even if the server
 
2371
        were active */
 
2372
 
 
2373
        n_pages_purged = 1;
 
2374
 
 
2375
        last_flush_time = time(NULL);
 
2376
 
 
2377
        while (n_pages_purged) {
 
2378
 
 
2379
                if (srv_fast_shutdown && srv_shutdown_state > 0) {
 
2380
 
 
2381
                        goto background_loop;
 
2382
                }
 
2383
 
 
2384
                srv_main_thread_op_info = "purging";
 
2385
                n_pages_purged = trx_purge();
 
2386
 
 
2387
                current_time = time(NULL);
 
2388
 
 
2389
                if (difftime(current_time, last_flush_time) > 1) {
 
2390
                        srv_main_thread_op_info = "flushing log";
 
2391
 
 
2392
                        log_buffer_flush_to_disk();
 
2393
                        last_flush_time = current_time;
 
2394
                }
 
2395
        }
 
2396
 
 
2397
        srv_main_thread_op_info = "flushing buffer pool pages";
 
2398
 
 
2399
        /* Flush a few oldest pages to make a new checkpoint younger */
 
2400
 
 
2401
        if (buf_get_modified_ratio_pct() > 70) {
 
2402
 
 
2403
                /* If there are lots of modified pages in the buffer pool
 
2404
                (> 70 %), we assume we can afford reserving the disk(s) for
 
2405
                the time it requires to flush 100 pages */
 
2406
 
 
2407
                n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100,
 
2408
                                                  ut_dulint_max);
 
2409
        } else {
 
2410
                /* Otherwise, we only flush a small number of pages so that
 
2411
                we do not unnecessarily use much disk i/o capacity from
 
2412
                other work */
 
2413
 
 
2414
                n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 10,
 
2415
                                                  ut_dulint_max);
 
2416
        }
 
2417
 
 
2418
        srv_main_thread_op_info = "making checkpoint";
 
2419
 
 
2420
        /* Make a new checkpoint about once in 10 seconds */
 
2421
 
 
2422
        log_checkpoint(TRUE, FALSE);
 
2423
 
 
2424
        srv_main_thread_op_info = "reserving kernel mutex";
 
2425
 
 
2426
        mutex_enter(&kernel_mutex);
 
2427
 
 
2428
        /* ---- When there is database activity, we jump from here back to
 
2429
        the start of loop */
 
2430
 
 
2431
        if (srv_activity_count != old_activity_count) {
 
2432
                mutex_exit(&kernel_mutex);
 
2433
                goto loop;
 
2434
        }
 
2435
 
 
2436
        mutex_exit(&kernel_mutex);
 
2437
 
 
2438
        /* If the database is quiet, we enter the background loop */
 
2439
 
 
2440
        /*****************************************************************/
 
2441
background_loop:
 
2442
        /* ---- In this loop we run background operations when the server
 
2443
        is quiet from user activity. Also in the case of a shutdown, we
 
2444
        loop here, flushing the buffer pool to the data files. */
 
2445
 
 
2446
        /* The server has been quiet for a while: start running background
 
2447
        operations */
 
2448
 
 
2449
        srv_main_thread_op_info = "doing background drop tables";
 
2450
 
 
2451
        n_tables_to_drop = row_drop_tables_for_mysql_in_background();
 
2452
 
 
2453
        if (n_tables_to_drop > 0) {
 
2454
                /* Do not monopolize the CPU even if there are tables waiting
 
2455
                in the background drop queue. (It is essentially a bug if
 
2456
                MySQL tries to drop a table while there are still open handles
 
2457
                to it and we had to put it to the background drop queue.) */
 
2458
 
 
2459
                os_thread_sleep(100000);
 
2460
        }
 
2461
 
 
2462
        srv_main_thread_op_info = "purging";
 
2463
 
 
2464
        /* Run a full purge */
 
2465
 
 
2466
        n_pages_purged = 1;
 
2467
 
 
2468
        last_flush_time = time(NULL);
 
2469
 
 
2470
        while (n_pages_purged) {
 
2471
                if (srv_fast_shutdown && srv_shutdown_state > 0) {
 
2472
 
 
2473
                        break;
 
2474
                }
 
2475
 
 
2476
                srv_main_thread_op_info = "purging";
 
2477
                n_pages_purged = trx_purge();
 
2478
 
 
2479
                current_time = time(NULL);
 
2480
 
 
2481
                if (difftime(current_time, last_flush_time) > 1) {
 
2482
                        srv_main_thread_op_info = "flushing log";
 
2483
 
 
2484
                        log_buffer_flush_to_disk();
 
2485
                        last_flush_time = current_time;
 
2486
                }
 
2487
        }
 
2488
 
 
2489
        srv_main_thread_op_info = "reserving kernel mutex";
 
2490
 
 
2491
        mutex_enter(&kernel_mutex);
 
2492
        if (srv_activity_count != old_activity_count) {
 
2493
                mutex_exit(&kernel_mutex);
 
2494
                goto loop;
 
2495
        }
 
2496
        mutex_exit(&kernel_mutex);
 
2497
 
 
2498
        srv_main_thread_op_info = "doing insert buffer merge";
 
2499
 
 
2500
        if (srv_fast_shutdown && srv_shutdown_state > 0) {
 
2501
                n_bytes_merged = 0;
 
2502
        } else {
 
2503
                n_bytes_merged = ibuf_contract_for_n_pages(
 
2504
                        TRUE, srv_insert_buffer_batch_size);
 
2505
        }
 
2506
 
 
2507
        srv_main_thread_op_info = "reserving kernel mutex";
 
2508
 
 
2509
        mutex_enter(&kernel_mutex);
 
2510
        if (srv_activity_count != old_activity_count) {
 
2511
                mutex_exit(&kernel_mutex);
 
2512
                goto loop;
 
2513
        }
 
2514
        mutex_exit(&kernel_mutex);
 
2515
 
 
2516
flush_loop:
 
2517
        srv_main_thread_op_info = "flushing buffer pool pages";
 
2518
 
 
2519
        if (srv_fast_shutdown < 2) {
 
2520
                n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100,
 
2521
                                                  ut_dulint_max);
 
2522
        } else {
 
2523
                /* In the fastest shutdown we do not flush the buffer pool
 
2524
                to data files: we set n_pages_flushed to 0 artificially. */
 
2525
 
 
2526
                n_pages_flushed = 0;
 
2527
        }
 
2528
 
 
2529
        srv_main_thread_op_info = "reserving kernel mutex";
 
2530
 
 
2531
        mutex_enter(&kernel_mutex);
 
2532
        if (srv_activity_count != old_activity_count) {
 
2533
                mutex_exit(&kernel_mutex);
 
2534
                goto loop;
 
2535
        }
 
2536
        mutex_exit(&kernel_mutex);
 
2537
 
 
2538
        srv_main_thread_op_info = "waiting for buffer pool flush to end";
 
2539
        buf_flush_wait_batch_end(BUF_FLUSH_LIST);
 
2540
 
 
2541
        srv_main_thread_op_info = "flushing log";
 
2542
 
 
2543
        log_buffer_flush_to_disk();
 
2544
 
 
2545
        srv_main_thread_op_info = "making checkpoint";
 
2546
 
 
2547
        log_checkpoint(TRUE, FALSE);
 
2548
 
 
2549
        if (buf_get_modified_ratio_pct() > srv_max_buf_pool_modified_pct) {
 
2550
 
 
2551
                /* Try to keep the number of modified pages in the
 
2552
                buffer pool under the limit wished by the user */
 
2553
 
 
2554
                goto flush_loop;
 
2555
        }
 
2556
 
 
2557
        srv_main_thread_op_info = "reserving kernel mutex";
 
2558
 
 
2559
        mutex_enter(&kernel_mutex);
 
2560
        if (srv_activity_count != old_activity_count) {
 
2561
                mutex_exit(&kernel_mutex);
 
2562
                goto loop;
 
2563
        }
 
2564
        mutex_exit(&kernel_mutex);
 
2565
        /*
 
2566
        srv_main_thread_op_info = "archiving log (if log archive is on)";
 
2567
 
 
2568
        log_archive_do(FALSE, &n_bytes_archived);
 
2569
        */
 
2570
        n_bytes_archived = 0;
 
2571
 
 
2572
        /* Keep looping in the background loop if still work to do */
 
2573
 
 
2574
        if (srv_fast_shutdown && srv_shutdown_state > 0) {
 
2575
                if (n_tables_to_drop + n_pages_flushed
 
2576
                    + n_bytes_archived != 0) {
 
2577
 
 
2578
                        /* If we are doing a fast shutdown (= the default)
 
2579
                        we do not do purge or insert buffer merge. But we
 
2580
                        flush the buffer pool completely to disk.
 
2581
                        In a 'very fast' shutdown we do not flush the buffer
 
2582
                        pool to data files: we have set n_pages_flushed to
 
2583
                        0 artificially. */
 
2584
 
 
2585
                        goto background_loop;
 
2586
                }
 
2587
        } else if (n_tables_to_drop
 
2588
                   + n_pages_purged + n_bytes_merged + n_pages_flushed
 
2589
                   + n_bytes_archived != 0) {
 
2590
                /* In a 'slow' shutdown we run purge and the insert buffer
 
2591
                merge to completion */
 
2592
 
 
2593
                goto background_loop;
 
2594
        }
 
2595
 
 
2596
        /* There is no work for background operations either: suspend
 
2597
        master thread to wait for more server activity */
 
2598
 
 
2599
suspend_thread:
 
2600
        srv_main_thread_op_info = "suspending";
 
2601
 
 
2602
        mutex_enter(&kernel_mutex);
 
2603
 
 
2604
        if (row_get_background_drop_list_len_low() > 0) {
 
2605
                mutex_exit(&kernel_mutex);
 
2606
 
 
2607
                goto loop;
 
2608
        }
 
2609
 
 
2610
        event = srv_suspend_thread();
 
2611
 
 
2612
        mutex_exit(&kernel_mutex);
 
2613
 
 
2614
        /* DO NOT CHANGE THIS STRING. innobase_start_or_create_for_mysql()
 
2615
        waits for database activity to die down when converting < 4.1.x
 
2616
        databases, and relies on this string being exactly as it is. InnoDB
 
2617
        manual also mentions this string in several places. */
 
2618
        srv_main_thread_op_info = "waiting for server activity";
 
2619
 
 
2620
        os_event_wait(event);
 
2621
 
 
2622
        if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
 
2623
                /* This is only extra safety, the thread should exit
 
2624
                already when the event wait ends */
 
2625
 
 
2626
                os_thread_exit(NULL);
 
2627
        }
 
2628
 
 
2629
        /* When there is user activity, InnoDB will set the event and the
 
2630
        main thread goes back to loop. */
 
2631
 
 
2632
        goto loop;
 
2633
 
 
2634
        OS_THREAD_DUMMY_RETURN; /* Not reached, avoid compiler warning */
 
2635
}
 
2636
#endif /* !UNIV_HOTBACKUP */