673
656
sys_header = trx_sysf_get(&mtr);
675
mlog_write_ull(sys_header + TRX_SYS_TRX_ID_STORE,
676
trx_sys->max_trx_id, &mtr);
658
mlog_write_dulint(sys_header + TRX_SYS_TRX_ID_STORE,
659
trx_sys->max_trx_id, &mtr);
677
660
mtr_commit(&mtr);
663
/*****************************************************************//**
664
Updates the offset information about the end of the MySQL binlog entry
665
which corresponds to the transaction just being committed. In a MySQL
666
replication slave updates the latest master binlog position up to which
667
replication has proceeded. */
682
trx_sys_flush_commit_id(uint64_t commit_id, ulint field, mtr_t* mtr)
670
trx_sys_update_mysql_binlog_offset(
671
/*===============================*/
672
const char* file_name,/*!< in: MySQL log file name */
673
ib_int64_t offset, /*!< in: position in that log file */
674
ulint field, /*!< in: offset of the MySQL log info field in
675
the trx sys header */
676
mtr_t* mtr) /*!< in: mtr */
684
trx_sysf_t* sys_header;
678
trx_sysf_t* sys_header;
680
if (ut_strlen(file_name) >= TRX_SYS_MYSQL_LOG_NAME_LEN) {
682
/* We cannot fit the name to the 512 bytes we have reserved */
686
687
sys_header = trx_sysf_get(mtr);
688
mlog_write_ull(sys_header + field + TRX_SYS_DRIZZLE_MAX_COMMIT_ID,
689
if (mach_read_from_4(sys_header + field
690
+ TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
691
!= TRX_SYS_MYSQL_LOG_MAGIC_N) {
693
mlog_write_ulint(sys_header + field
694
+ TRX_SYS_MYSQL_LOG_MAGIC_N_FLD,
695
TRX_SYS_MYSQL_LOG_MAGIC_N,
699
if (0 != strcmp((char*) (sys_header + field + TRX_SYS_MYSQL_LOG_NAME),
702
mlog_write_string(sys_header + field
703
+ TRX_SYS_MYSQL_LOG_NAME,
704
(byte*) file_name, 1 + ut_strlen(file_name),
708
if (mach_read_from_4(sys_header + field
709
+ TRX_SYS_MYSQL_LOG_OFFSET_HIGH) > 0
710
|| (offset >> 32) > 0) {
712
mlog_write_ulint(sys_header + field
713
+ TRX_SYS_MYSQL_LOG_OFFSET_HIGH,
714
(ulint)(offset >> 32),
718
mlog_write_ulint(sys_header + field
719
+ TRX_SYS_MYSQL_LOG_OFFSET_LOW,
720
(ulint)(offset & 0xFFFFFFFFUL),
724
/*****************************************************************//**
725
Stores the MySQL binlog offset info in the trx system header if
726
the magic number shows it valid, and print the info to stderr */
695
trx_sys_read_commit_id(void)
729
trx_sys_print_mysql_binlog_offset(void)
696
730
/*===================================*/
698
trx_sysf_t* sys_header;
703
sys_header = trx_sysf_get(&mtr);
705
trx_sys_commit_id = mach_read_from_8(sys_header + TRX_SYS_DRIZZLE_LOG_INFO
706
+ TRX_SYS_DRIZZLE_MAX_COMMIT_ID);
732
trx_sysf_t* sys_header;
734
ulint trx_sys_mysql_bin_log_pos_high;
735
ulint trx_sys_mysql_bin_log_pos_low;
739
sys_header = trx_sysf_get(&mtr);
741
if (mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO
742
+ TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
743
!= TRX_SYS_MYSQL_LOG_MAGIC_N) {
750
trx_sys_mysql_bin_log_pos_high = mach_read_from_4(
751
sys_header + TRX_SYS_MYSQL_LOG_INFO
752
+ TRX_SYS_MYSQL_LOG_OFFSET_HIGH);
753
trx_sys_mysql_bin_log_pos_low = mach_read_from_4(
754
sys_header + TRX_SYS_MYSQL_LOG_INFO
755
+ TRX_SYS_MYSQL_LOG_OFFSET_LOW);
757
trx_sys_mysql_bin_log_pos
758
= (((ib_int64_t)trx_sys_mysql_bin_log_pos_high) << 32)
759
+ (ib_int64_t)trx_sys_mysql_bin_log_pos_low;
761
ut_memcpy(trx_sys_mysql_bin_log_name,
762
sys_header + TRX_SYS_MYSQL_LOG_INFO
763
+ TRX_SYS_MYSQL_LOG_NAME, TRX_SYS_MYSQL_LOG_NAME_LEN);
766
"InnoDB: Last MySQL binlog file position %lu %lu,"
768
trx_sys_mysql_bin_log_pos_high, trx_sys_mysql_bin_log_pos_low,
769
trx_sys_mysql_bin_log_name);
774
/*****************************************************************//**
775
Prints to stderr the MySQL master log offset info in the trx system header if
776
the magic number shows it valid. */
779
trx_sys_print_mysql_master_log_pos(void)
780
/*====================================*/
782
trx_sysf_t* sys_header;
787
sys_header = trx_sysf_get(&mtr);
789
if (mach_read_from_4(sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
790
+ TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
791
!= TRX_SYS_MYSQL_LOG_MAGIC_N) {
799
"InnoDB: In a MySQL replication slave the last"
800
" master binlog file\n"
801
"InnoDB: position %lu %lu, file name %s\n",
802
(ulong) mach_read_from_4(sys_header
803
+ TRX_SYS_MYSQL_MASTER_LOG_INFO
804
+ TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
805
(ulong) mach_read_from_4(sys_header
806
+ TRX_SYS_MYSQL_MASTER_LOG_INFO
807
+ TRX_SYS_MYSQL_LOG_OFFSET_LOW),
808
sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
809
+ TRX_SYS_MYSQL_LOG_NAME);
810
/* Copy the master log position info to global variables we can
811
use in ha_innobase.cc to initialize glob_mi to right values */
813
ut_memcpy(trx_sys_mysql_master_log_name,
814
sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
815
+ TRX_SYS_MYSQL_LOG_NAME,
816
TRX_SYS_MYSQL_LOG_NAME_LEN);
818
trx_sys_mysql_master_log_pos
819
= (((ib_int64_t) mach_read_from_4(
820
sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
821
+ TRX_SYS_MYSQL_LOG_OFFSET_HIGH)) << 32)
822
+ ((ib_int64_t) mach_read_from_4(
823
sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
824
+ TRX_SYS_MYSQL_LOG_OFFSET_LOW));
708
825
mtr_commit(&mtr);
786
902
sys_header = trx_sysf_get(mtr);
788
904
/* Start counting transaction ids from number 1 up */
789
mach_write_to_8(sys_header + TRX_SYS_TRX_ID_STORE, 1);
791
/* Reset the rollback segment slots. Old versions of InnoDB
792
define TRX_SYS_N_RSEGS as 256 (TRX_SYS_OLD_N_RSEGS) and expect
793
that the whole array is initialized. */
794
ptr = TRX_SYS_RSEGS + sys_header;
795
len = ut_max(TRX_SYS_OLD_N_RSEGS, TRX_SYS_N_RSEGS)
796
* TRX_SYS_RSEG_SLOT_SIZE;
797
memset(ptr, 0xff, len);
799
ut_a(ptr <= page + (UNIV_PAGE_SIZE - FIL_PAGE_DATA_END));
801
/* Initialize all of the page. This part used to be uninitialized. */
802
memset(ptr, 0, UNIV_PAGE_SIZE - FIL_PAGE_DATA_END + page - ptr);
804
mlog_log_string(sys_header, UNIV_PAGE_SIZE - FIL_PAGE_DATA_END
805
+ page - sys_header, mtr);
905
mlog_write_dulint(sys_header + TRX_SYS_TRX_ID_STORE,
906
ut_dulint_create(0, 1), mtr);
908
/* Reset the rollback segment slots */
909
for (i = 0; i < TRX_SYS_N_RSEGS; i++) {
911
trx_sysf_rseg_set_space(sys_header, i, ULINT_UNDEFINED, mtr);
912
trx_sysf_rseg_set_page_no(sys_header, i, FIL_NULL, mtr);
915
/* The remaining area (up to the page trailer) is uninitialized.
916
Silence Valgrind warnings about it. */
917
UNIV_MEM_VALID(sys_header + (TRX_SYS_RSEGS
918
+ TRX_SYS_N_RSEGS * TRX_SYS_RSEG_SLOT_SIZE
919
+ TRX_SYS_RSEG_SPACE),
920
(UNIV_PAGE_SIZE - FIL_PAGE_DATA_END
922
+ TRX_SYS_N_RSEGS * TRX_SYS_RSEG_SLOT_SIZE
923
+ TRX_SYS_RSEG_SPACE))
924
+ page - sys_header);
807
926
/* Create the first rollback segment in the SYSTEM tablespace */
808
slot_no = trx_sysf_rseg_find_free(mtr);
809
page_no = trx_rseg_header_create(TRX_SYS_SPACE, 0, ULINT_MAX, slot_no,
927
page_no = trx_rseg_header_create(TRX_SYS_SPACE, 0, ULINT_MAX, &slot_no,
811
929
ut_a(slot_no == TRX_SYS_SYSTEM_RSEG_ID);
812
ut_a(page_no == FSP_FIRST_RSEG_PAGE_NO);
930
ut_a(page_no != FIL_NULL);
814
932
mutex_exit(&kernel_mutex);
1176
1302
/* Does nothing at the moment */
1179
/*********************************************************************
1180
Creates the rollback segments */
1183
trx_sys_create_rsegs(
1184
/*=================*/
1185
ulint n_rsegs) /*!< number of rollback segments to create */
1187
ulint new_rsegs = 0;
1189
/* Do not create additional rollback segments if
1190
innodb_force_recovery has been set and the database
1191
was not shutdown cleanly. */
1192
if (!srv_force_recovery && !recv_needed_recovery) {
1195
for (i = 0; i < n_rsegs; ++i) {
1197
if (trx_rseg_create() != NULL) {
1205
if (new_rsegs > 0) {
1207
"InnoDB: %lu rollback segment(s) active.\n",
1212
1304
#else /* !UNIV_HOTBACKUP */
1305
/*****************************************************************//**
1306
Prints to stderr the MySQL binlog info in the system header if the
1307
magic number shows it valid. */
1310
trx_sys_print_mysql_binlog_offset_from_page(
1311
/*========================================*/
1312
const byte* page) /*!< in: buffer containing the trx
1313
system header page, i.e., page number
1314
TRX_SYS_PAGE_NO in the tablespace */
1316
const trx_sysf_t* sys_header;
1318
sys_header = page + TRX_SYS;
1320
if (mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO
1321
+ TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
1322
== TRX_SYS_MYSQL_LOG_MAGIC_N) {
1325
"ibbackup: Last MySQL binlog file position %lu %lu,"
1327
(ulong) mach_read_from_4(
1328
sys_header + TRX_SYS_MYSQL_LOG_INFO
1329
+ TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
1330
(ulong) mach_read_from_4(
1331
sys_header + TRX_SYS_MYSQL_LOG_INFO
1332
+ TRX_SYS_MYSQL_LOG_OFFSET_LOW),
1333
sys_header + TRX_SYS_MYSQL_LOG_INFO
1334
+ TRX_SYS_MYSQL_LOG_NAME);
1214
1339
/* THESE ARE COPIED FROM NON-HOTBACKUP PART OF THE INNODB SOURCE TREE
1215
1340
(This code duplicaton should be fixed at some point!)
1411
1535
#endif /* !UNIV_HOTBACKUP */
1413
#ifndef UNIV_HOTBACKUP
1414
/*********************************************************************
1415
Shutdown/Close the transaction system. */
1424
ut_ad(trx_sys != NULL);
1426
/* Check that all read views are closed except read view owned
1429
if (UT_LIST_GET_LEN(trx_sys->view_list) > 1) {
1431
"InnoDB: Error: all read views were not closed"
1432
" before shutdown:\n"
1433
"InnoDB: %lu read views open \n",
1434
static_cast<ulint>(UT_LIST_GET_LEN(trx_sys->view_list)) - 1);
1437
sess_close(trx_dummy_sess);
1438
trx_dummy_sess = NULL;
1440
trx_purge_sys_close();
1442
mutex_enter(&kernel_mutex);
1444
/* Free the double write data structures. */
1445
ut_a(trx_doublewrite != NULL);
1446
ut_free(trx_doublewrite->write_buf_unaligned);
1447
trx_doublewrite->write_buf_unaligned = NULL;
1449
mem_free(trx_doublewrite->buf_block_arr);
1450
trx_doublewrite->buf_block_arr = NULL;
1452
mutex_free(&trx_doublewrite->mutex);
1453
mem_free(trx_doublewrite);
1454
trx_doublewrite = NULL;
1456
/* There can't be any active transactions. */
1457
rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
1459
while (rseg != NULL) {
1460
trx_rseg_t* prev_rseg = rseg;
1462
rseg = UT_LIST_GET_NEXT(rseg_list, prev_rseg);
1463
UT_LIST_REMOVE(rseg_list, trx_sys->rseg_list, prev_rseg);
1465
trx_rseg_mem_free(prev_rseg);
1468
view = UT_LIST_GET_FIRST(trx_sys->view_list);
1470
while (view != NULL) {
1471
read_view_t* prev_view = view;
1473
view = UT_LIST_GET_NEXT(view_list, prev_view);
1475
/* Views are allocated from the trx_sys->global_read_view_heap.
1476
So, we simply remove the element here. */
1477
UT_LIST_REMOVE(view_list, trx_sys->view_list, prev_view);
1480
ut_a(UT_LIST_GET_LEN(trx_sys->trx_list) == 0);
1481
ut_a(UT_LIST_GET_LEN(trx_sys->rseg_list) == 0);
1482
ut_a(UT_LIST_GET_LEN(trx_sys->view_list) == 0);
1483
ut_a(UT_LIST_GET_LEN(trx_sys->mysql_trx_list) == 0);
1488
mutex_exit(&kernel_mutex);
1490
#endif /* !UNIV_HOTBACKUP */