mirror of
https://github.com/MariaDB/server.git
synced 2026-04-23 08:45:33 +02:00
After applying the snapshots, ensure that code conforms to the final version of WL 3914. It is signficant that, after these changes, InnoDB does not define MYSQL_SERVER, and can be built as an independent storage engine plugin. Fixes: Bug#9709: InnoDB inconsistensy causes "Operating System Error 32/33" Bug#18828: If InnoDB runs out of undo slots, it returns misleading 'table is full' Bug#20090: InnoDB: Error: trying to declare trx to enter InnoDB Bug#20352: Make ibuf_contract_for_n_pages tunable Bug#21101: Wrong error on exceeding max row size for InnoDB table Bug#21293: Deadlock detection prefers to kill long running FOR UPDATE queries Bug#22819: SHOW INNODB STATUS crashes the server with an assertion failure under high load Bug#25078: Make the replication thread to ignore innodb_thread_concurrency Bug#25645: Assertion failure in file srv0srv.c Bug#28138: indexing column prefixes produces corruption in InnoDB BitKeeper/deleted/.del-Makefile.am~55504c43d99979e4: Delete: storage/innobase/buf/Makefile.am BitKeeper/deleted/.del-Makefile.am~79bb55303929b560: Delete: storage/innobase/dict/Makefile.am BitKeeper/deleted/.del-Makefile.am~7cd88e5f9a8d7ce8: Delete: storage/innobase/data/Makefile.am BitKeeper/deleted/.del-Makefile.am~e19a1fb29b1fe527: Delete: storage/innobase/btr/Makefile.am BitKeeper/deleted/.del-Makefile.am~4ae65b009d41d1d: Delete: storage/innobase/eval/Makefile.am BitKeeper/deleted/.del-Makefile.am~679131a02af3f6fb: Delete: storage/innobase/fsp/Makefile.am BitKeeper/deleted/.del-Makefile.am~6acac9ae30eabdb3: Delete: storage/innobase/dyn/Makefile.am BitKeeper/deleted/.del-Makefile.am~a5e6b4385717fcb7: Delete: storage/innobase/fil/Makefile.am BitKeeper/deleted/.del-Makefile.am~11d601934b49c19: Delete: storage/innobase/fut/Makefile.am BitKeeper/deleted/.del-Makefile.am~5aab37bf3b6c430: Delete: storage/innobase/ibuf/Makefile.am BitKeeper/deleted/.del-Makefile.am~af2d719bb6e66986: Delete: storage/innobase/handler/Makefile.am BitKeeper/deleted/.del-Makefile.am~f0dbbc7a78648e18: Delete: storage/innobase/ha/Makefile.am BitKeeper/deleted/.del-Makefile.am~41684e54a5b0d26a: Delete: storage/innobase/log/Makefile.am BitKeeper/deleted/.del-Makefile.am~edd95d7290ddeff3: Delete: storage/innobase/lock/Makefile.am BitKeeper/deleted/.del-Makefile.i: Delete: storage/innobase/include/Makefile.i BitKeeper/deleted/.del-Makefile.am~2a6ccdba41b591a3: Delete: storage/innobase/mach/Makefile.am BitKeeper/deleted/.del-Makefile.am~2bd35bda856342: Delete: storage/innobase/os/Makefile.am BitKeeper/deleted/.del-Makefile.am~8448688c5ab92132: Delete: storage/innobase/mem/Makefile.am BitKeeper/deleted/.del-Makefile.am~b5a7a8cfa711b6de: Delete: storage/innobase/mtr/Makefile.am BitKeeper/deleted/.del-Makefile.am~2cee8a309eb8eee2: Delete: storage/innobase/page/Makefile.am BitKeeper/deleted/.del-Makefile.am~3d0553f8aa9c456b: Delete: storage/innobase/read/Makefile.am BitKeeper/deleted/.del-Makefile.am~7b0c4abae6684f8c: Delete: storage/innobase/pars/Makefile.am BitKeeper/deleted/.del-Makefile.am~d0e0dd55cbd413f0: Delete: storage/innobase/que/Makefile.am BitKeeper/deleted/.del-Makefile.am~20a219ccf7825d65: Delete: storage/innobase/row/Makefile.am BitKeeper/deleted/.del-Makefile.am~37bdfb2973b2442b: Delete: storage/innobase/rem/Makefile.am BitKeeper/deleted/.del-Makefile.am~557098c4e5c01ee2: Delete: storage/innobase/thr/Makefile.am BitKeeper/deleted/.del-Makefile.am~fdfe12f48c2499af: Delete: storage/innobase/sync/Makefile.am BitKeeper/deleted/.del-Makefile.am~feb2280a52035d8d: Delete: storage/innobase/srv/Makefile.am BitKeeper/deleted/.del-Makefile.am~456d34c4816dbda4: Delete: storage/innobase/ut/Makefile.am BitKeeper/deleted/.del-Makefile.am~5ec2ef0d2c35e138: Delete: storage/innobase/usr/Makefile.am BitKeeper/deleted/.del-Makefile.am~d25c456e48393313: Delete: storage/innobase/trx/Makefile.am mysql-test/r/innodb.result: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1421: Fix the innodb test by shifting some of the contents of the .result file. Approved by: Marko Revision r1422: Fix for Bug#21101 - returns wrong error message when table column defs exceed the max row size. The fix returns a more appropriate error message. Add a test case to innodb.test and expected output to innodb.result. mysql-test/t/innodb.test: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1422: Fix for Bug#21101 - returns wrong error message when table column defs exceed the max row size. The fix returns a more appropriate error message. Add a test case to innodb.test and expected output to innodb.result. storage/innobase/btr/btr0btr.c: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1546: When buffering an insert to a prefix index of a variable-length column, do not incorrectly mark the column as fixed-length. (Bug#28138) ibuf_entry_build(): Instead of prefix_len, pass fixed_len to dtype_new_store_for_order_and_null_size(). Add debug assertions. btr_index_rec_validate(): Correct a comment about prefix indexes. rec_get_converted_size_new(), rec_convert_dtuple_to_rec_new(): Add debug assertions and comments. dict_col_type_assert_equal(): New debug function. storage/innobase/data/data0data.c: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1490: Add #include <ctype.h>. Apparently, this header is no longer included by the common headers. This may be related to WL#2936 (pluggable storage engines). storage/innobase/data/data0type.c: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1513: Split ut_a(a && b [&& c...]); into separate ut_a(a); ut_a(b); [ut_a(c); ...]. This makes it possible to see which expression was false by looking at the error message. Approved by: Marko storage/innobase/dict/dict0crea.c: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1423: Fix for Bug#18828. Return DB_TOO_MANY_CONCURRENT_TRXS when we run out of UNDO slots in the rollback segment. This is a partial fix since the MySQL error code requested to properly report the error condition back to the client has not yet materialized. Currently we have #ifdef'd the error code translation in ha_innodb.cc. This will have to be changed as and when MySQl add the new requested code or an equivalent code that we can then use. Given the above, currently we will get the old behaviour, not the "fixed" and intended behaviour. storage/innobase/dict/dict0dict.c: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1490: Add #include <ctype.h>. Apparently, this header is no longer included by the common headers. This may be related to WL#2936 (pluggable storage engines). Revision r1513: Split ut_a(a && b [&& c...]); into separate ut_a(a); ut_a(b); [ut_a(c); ...]. This makes it possible to see which expression was false by looking at the error message. Approved by: Marko Revision r1528: Define an auxiliary macro UT_BITS_IN_BYTES() and use it where possible. Revision r1529: Revert r799, which was supposed to prevent similar cases as Bug#21638. In reality, the patch breaks the handling of prefix indexes of variable-length columns in ROW_FORMAT=COMPACT. Reverting the patch is only a partial fix of Bug#28138. Revision r1535: Document that DICT_MAX_INDEX_COL_LEN must not be changed. storage/innobase/fsp/fsp0fsp.c: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1513: Split ut_a(a && b [&& c...]); into separate ut_a(a); ut_a(b); [ut_a(c); ...]. This makes it possible to see which expression was false by looking at the error message. Approved by: Marko Revision r1528: Define an auxiliary macro UT_BITS_IN_BYTES() and use it where possible. storage/innobase/ibuf/ibuf0ibuf.c: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1420: Output to the error log information about the limitations of UNIV_IBUF_DEBUG. innobase_start_or_create_for_mysql(): Note that crash recovery is broken when UNIV_IBUF_DEBUG is defined. ibuf_counts[]: Make this a two-dimensional array. No need to allocate anything from the heap. Eliminate ibuf_counts_inited, as the array will be zero-filled by the runtime environment. ibuf_count_check(): New function, to print out an explanation before assertion failure. Revision r1528: Define an auxiliary macro UT_BITS_IN_BYTES() and use it where possible. Revision r1546: When buffering an insert to a prefix index of a variable-length column, do not incorrectly mark the column as fixed-length. (Bug#28138) ibuf_entry_build(): Instead of prefix_len, pass fixed_len to dtype_new_store_for_order_and_null_size(). Add debug assertions. btr_index_rec_validate(): Correct a comment about prefix indexes. rec_get_converted_size_new(), rec_convert_dtuple_to_rec_new(): Add debug assertions and comments. dict_col_type_assert_equal(): New debug function. storage/innobase/include/db0err.h: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1423: Fix for Bug#18828. Return DB_TOO_MANY_CONCURRENT_TRXS when we run out of UNDO slots in the rollback segment. This is a partial fix since the MySQL error code requested to properly report the error condition back to the client has not yet materialized. Currently we have #ifdef'd the error code translation in ha_innodb.cc. This will have to be changed as and when MySQl add the new requested code or an equivalent code that we can then use. Given the above, currently we will get the old behaviour, not the "fixed" and intended behaviour. storage/innobase/include/dict0dict.h: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1546: When buffering an insert to a prefix index of a variable-length column, do not incorrectly mark the column as fixed-length. (Bug#28138) ibuf_entry_build(): Instead of prefix_len, pass fixed_len to dtype_new_store_for_order_and_null_size(). Add debug assertions. btr_index_rec_validate(): Correct a comment about prefix indexes. rec_get_converted_size_new(), rec_convert_dtuple_to_rec_new(): Add debug assertions and comments. dict_col_type_assert_equal(): New debug function. storage/innobase/include/dict0dict.ic: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1546: When buffering an insert to a prefix index of a variable-length column, do not incorrectly mark the column as fixed-length. (Bug#28138) ibuf_entry_build(): Instead of prefix_len, pass fixed_len to dtype_new_store_for_order_and_null_size(). Add debug assertions. btr_index_rec_validate(): Correct a comment about prefix indexes. rec_get_converted_size_new(), rec_convert_dtuple_to_rec_new(): Add debug assertions and comments. dict_col_type_assert_equal(): New debug function. storage/innobase/include/dict0mem.h: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1535: Document that DICT_MAX_INDEX_COL_LEN must not be changed. Revision r1536: Change the comment to a more appropriate one. Discussed with Heikki on IM. Approved by: Heikki storage/innobase/include/ha_prototypes.h: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1482: Fix Bug#25078 by always letting the replication thread on the slave server to enter InnoDB. This can be made further customizable by the user if we introduce a new config parameter. This will wait until config parameters can be easily added. Approved by: Marko Revision r1501: Fix Bug#21293: Consider transactions that had edited non-transactional tables heavier than ones that had not. This helps killing the "right" transaction in case of a deadlock. Approved by: Heikki storage/innobase/include/os0file.h: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1431: Fix Bug#9709 by retrying (forever) if ERROR_SHARING_VIOLATION or ERROR_LOCK_VIOLATION is encountered during file operation. This is caused by backup software, so InnoDB should retry while the backup software is done with the file. Approved by: Heikki storage/innobase/include/rem0rec.ic: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1569: Fix some in:/out: comments. Approved by: Marko storage/innobase/include/row0mysql.h: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1422: Fix for Bug#21101 - returns wrong error message when table column defs exceed the max row size. The fix returns a more appropriate error message. Add a test case to innodb.test and expected output to innodb.result. storage/innobase/include/trx0trx.h: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1462: Fix typo in comment. Revision r1486: Improve the comment for trx_struct::undo_no. Suggested by: Heikki Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1497: Add the number of locks acquired by a transaction to its weight when choosing the lightest transaction to kill when a deadlock occurs. This fixes Bug#21293 partially. Approved by: Heikki Revision r1501: Fix Bug#21293: Consider transactions that had edited non-transactional tables heavier than ones that had not. This helps killing the "right" transaction in case of a deadlock. Approved by: Heikki storage/innobase/include/trx0undo.h: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1423: Fix for Bug#18828. Return DB_TOO_MANY_CONCURRENT_TRXS when we run out of UNDO slots in the rollback segment. This is a partial fix since the MySQL error code requested to properly report the error condition back to the client has not yet materialized. Currently we have #ifdef'd the error code translation in ha_innodb.cc. This will have to be changed as and when MySQl add the new requested code or an equivalent code that we can then use. Given the above, currently we will get the old behaviour, not the "fixed" and intended behaviour. storage/innobase/include/ut0ut.h: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1528: Define an auxiliary macro UT_BITS_IN_BYTES() and use it where possible. storage/innobase/lock/lock0lock.c: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1457: Fix Bug#22819, remove assertion. (http://bugs.mysql.com/bug.php?id=22819) Revision r1497: Add the number of locks acquired by a transaction to its weight when choosing the lightest transaction to kill when a deadlock occurs. This fixes Bug#21293 partially. Approved by: Heikki Revision r1513: Split ut_a(a && b [&& c...]); into separate ut_a(a); ut_a(b); [ut_a(c); ...]. This makes it possible to see which expression was false by looking at the error message. Approved by: Marko storage/innobase/log/log0log.c: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1521: Forward port r1520 from branches/5.0 Patch to allow monitor threads to stop before proceeding with normal shutdown. Also have a separate time counter for tablespace monitor. reviewed by: Heikki Revision r1524: Undo bad space formatting introduced in earlier commit r1521 spotted by: Marko Revision r1533: logs_empty_and_mark_files_at_shutdown(): Remove trailing whitespace that was added in r1521. storage/innobase/os/os0file.c: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1431: Fix Bug#9709 by retrying (forever) if ERROR_SHARING_VIOLATION or ERROR_LOCK_VIOLATION is encountered during file operation. This is caused by backup software, so InnoDB should retry while the backup software is done with the file. Approved by: Heikki storage/innobase/rem/rem0rec.c: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1528: Define an auxiliary macro UT_BITS_IN_BYTES() and use it where possible. Revision r1531: rec_get_converted_size_new(): Simplify and move a debug assertion. Revision r1546: When buffering an insert to a prefix index of a variable-length column, do not incorrectly mark the column as fixed-length. (Bug#28138) ibuf_entry_build(): Instead of prefix_len, pass fixed_len to dtype_new_store_for_order_and_null_size(). Add debug assertions. btr_index_rec_validate(): Correct a comment about prefix indexes. rec_get_converted_size_new(), rec_convert_dtuple_to_rec_new(): Add debug assertions and comments. dict_col_type_assert_equal(): New debug function. Revision r1555: rec_get_converted_size_new(): The total size of the infimum and supremum records in ROW_FORMAT=COMPACT is REC_N_NEW_EXTRA_BYTES + 8. The REC_N_NEW_EXTRA_BYTES was accidentally omitted in r1546. This function should never be called on those records, though. Revision r1569: Fix some in:/out: comments. Approved by: Marko storage/innobase/row/row0ins.c: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1485: Minor cleanup. row_ins_check_foreign_constraint(), row_ins_scan_sec_index_for_duplicate(): Make use of the predicates page_rec_is_infimum() and page_rec_is_supremum(). Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1513: Split ut_a(a && b [&& c...]); into separate ut_a(a); ut_a(b); [ut_a(c); ...]. This makes it possible to see which expression was false by looking at the error message. Approved by: Marko storage/innobase/row/row0mysql.c: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1422: Fix for Bug#21101 - returns wrong error message when table column defs exceed the max row size. The fix returns a more appropriate error message. Add a test case to innodb.test and expected output to innodb.result. Revision r1423: Fix for Bug#18828. Return DB_TOO_MANY_CONCURRENT_TRXS when we run out of UNDO slots in the rollback segment. This is a partial fix since the MySQL error code requested to properly report the error condition back to the client has not yet materialized. Currently we have #ifdef'd the error code translation in ha_innodb.cc. This will have to be changed as and when MySQl add the new requested code or an equivalent code that we can then use. Given the above, currently we will get the old behaviour, not the "fixed" and intended behaviour. storage/innobase/row/row0row.c: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1513: Split ut_a(a && b [&& c...]); into separate ut_a(a); ut_a(b); [ut_a(c); ...]. This makes it possible to see which expression was false by looking at the error message. Approved by: Marko Revision r1529: Revert r799, which was supposed to prevent similar cases as Bug#21638. In reality, the patch breaks the handling of prefix indexes of variable-length columns in ROW_FORMAT=COMPACT. Reverting the patch is only a partial fix of Bug#28138. storage/innobase/row/row0sel.c: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1452: Fix phantom reads (http://bugs.mysql.com/27197) following Heikki's patch in the bug followup. Approved by: Heikki Revision r1455: Reindent with tabs instead of spaces. Spotted by: Marko storage/innobase/srv/srv0srv.c: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1424: Bug#20352. Added variable srv_insert_buffer_batch_size. We want to make this variable settable. Since the pluggable engine interface currently doesn't provide a usable mechanism, we will add the latter functionality once it's available. Revision r1426: Fix code indentation from r1424. Revision r1459: Fix typo in the comment. Revision r1482: Fix Bug#25078 by always letting the replication thread on the slave server to enter InnoDB. This can be made further customizable by the user if we introduce a new config parameter. This will wait until config parameters can be easily added. Approved by: Marko Revision r1487: Fix typo in comment. Spotted by: Marko Revision r1521: Forward port r1520 from branches/5.0 Patch to allow monitor threads to stop before proceeding with normal shutdown. Also have a separate time counter for tablespace monitor. reviewed by: Heikki Revision r1532: srv_lock_timeout_and_monitor_thread(): Correct the indentation that was broken in r1521. Revision r1553: Fix Bug#20090 as suggested in the bug followup by Heikki. Approved by: Heikki storage/innobase/srv/srv0start.c: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1420: Output to the error log information about the limitations of UNIV_IBUF_DEBUG. innobase_start_or_create_for_mysql(): Note that crash recovery is broken when UNIV_IBUF_DEBUG is defined. ibuf_counts[]: Make this a two-dimensional array. No need to allocate anything from the heap. Eliminate ibuf_counts_inited, as the array will be zero-filled by the runtime environment. ibuf_count_check(): New function, to print out an explanation before assertion failure. storage/innobase/sync/sync0arr.c: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1513: Split ut_a(a && b [&& c...]); into separate ut_a(a); ut_a(b); [ut_a(c); ...]. This makes it possible to see which expression was false by looking at the error message. Approved by: Marko storage/innobase/trx/trx0rec.c: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1423: Fix for Bug#18828. Return DB_TOO_MANY_CONCURRENT_TRXS when we run out of UNDO slots in the rollback segment. This is a partial fix since the MySQL error code requested to properly report the error condition back to the client has not yet materialized. Currently we have #ifdef'd the error code translation in ha_innodb.cc. This will have to be changed as and when MySQl add the new requested code or an equivalent code that we can then use. Given the above, currently we will get the old behaviour, not the "fixed" and intended behaviour. storage/innobase/trx/trx0trx.c: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1491: Fix typo in comment. Revision r1497: Add the number of locks acquired by a transaction to its weight when choosing the lightest transaction to kill when a deadlock occurs. This fixes Bug#21293 partially. Approved by: Heikki Revision r1501: Fix Bug#21293: Consider transactions that had edited non-transactional tables heavier than ones that had not. This helps killing the "right" transaction in case of a deadlock. Approved by: Heikki Revision r1522: trx0trx.c: Add missing #include "ha_prototypes.h". storage/innobase/trx/trx0undo.c: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1423: Fix for Bug#18828. Return DB_TOO_MANY_CONCURRENT_TRXS when we run out of UNDO slots in the rollback segment. This is a partial fix since the MySQL error code requested to properly report the error condition back to the client has not yet materialized. Currently we have #ifdef'd the error code translation in ha_innodb.cc. This will have to be changed as and when MySQl add the new requested code or an equivalent code that we can then use. Given the above, currently we will get the old behaviour, not the "fixed" and intended behaviour. storage/innobase/ut/ut0ut.c: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1490: Add #include <ctype.h>. Apparently, this header is no longer included by the common headers. This may be related to WL#2936 (pluggable storage engines). mysql-test/r/innodb_trx_weight.result: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1498: Add a test about the behavior introduced in r1497. Revision r1501: Fix Bug#21293: Consider transactions that had edited non-transactional tables heavier than ones that had not. This helps killing the "right" transaction in case of a deadlock. Approved by: Heikki mysql-test/include/innodb_trx_weight.inc: Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569. Revision r1501: Fix Bug#21293: Consider transactions that had edited non-transactional tables heavier than ones that had not. This helps killing the "right" transaction in case of a deadlock. Approved by: Heikki Revision r1556: mysql-test/innodb_trx_weight.inc: Add username root to the "connect" statement. The Unix user running mysql-test-run usually does not have any privileges on the MySQL test database. mysql-test/t/innodb_trx_weight.test: Fixes after merging InnoDB snapshots. Revision r1498: Add a test about the behavior introduced in r1497. Revision r1501: Fix Bug#21293: Consider transactions that had edited non-transactional tables heavier than ones that had not. This helps killing the "right" transaction in case of a deadlock. Approved by: Heikki sql/sql_class.cc: Fixes after merging InnoDB snapshots. storage/innobase/Makefile.am: Fixes after merging InnoDB snapshots. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. storage/innobase/handler/ha_innodb.cc: Fixes after merging InnoDB snapshots. Revision r1422: Fix for Bug#21101 - returns wrong error message when table column defs exceed the max row size. The fix returns a more appropriate error message. Add a test case to innodb.test and expected output to innodb.result. Revision r1423: Fix for Bug#18828. Return DB_TOO_MANY_CONCURRENT_TRXS when we run out of UNDO slots in the rollback segment. This is a partial fix since the MySQL error code requested to properly report the error condition back to the client has not yet materialized. Currently we have #ifdef'd the error code translation in ha_innodb.cc. This will have to be changed as and when MySQl add the new requested code or an equivalent code that we can then use. Given the above, currently we will get the old behaviour, not the "fixed" and intended behaviour. Revision r1425: Fixed a missing function decoration that slipped into r1422. Revision r1434: Fix typo. Revision r1442: Potential fix for Bug#25645: "Move innobase_release_stat_resources(trx) outside the 'if' in ha_innobase::external_lock(). That would add more safety that whatever MySQL does at a query end, there would be no risk of a hang on the btr search latch." Also call innobase_release_temporary_latches() in the beginning of ha_innobase::close(). Approved by: Heikki Revision r1453: Bugfix: only call innobase_release_temporary_latches() in case of current_thd is not NULL, otherwise we get NULL pointer dereferencing. Approved by: Heikki Revision r1474: Fix typo in comment: the exact prototype is in include/data0type.ic, not in data/data0type.ic Revision r1482: Fix Bug#25078 by always letting the replication thread on the slave server to enter InnoDB. This can be made further customizable by the user if we introduce a new config parameter. This will wait until config parameters can be easily added. Approved by: Marko Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. Revision r1489: thd_to_trx(), check_trx_exists(): Remove the handlerton parameter. It is a singleton object whose address is stored into innodb_hton_ptr. Revision r1492: Convert innobase_buffer_pool_size and innobase_log_file_size types from longlong to long long because MYSQL_SYSVAR_LONGLONG marco expects long long type. Also change ((ulint)innobase_buffer_pool_size) / 1024 to (ulint)(innobase_buffer_pool_size / 1024) and remove comment which is no longer true. Provided that innobase_buffer_pool_size is always 64bits these statements are equivalent if ulint is 64 bit (well it will screw up if innobase_buffer_pool_size is negative). And if ulint is 32 bit the later variant gives a little more chance that the value will fit. Approved by: Heikki Revision r1493: ha_innodb.cc: Remove the declarations of some global InnoDB variables whose name starts with srv_. These variables are declared in the header files that are covered by #include directives in ha_innodb.cc. Revision r1495: Introduce the function reset_template() for resetting some fields of row_prebuilt_t; currently prebuilt->read_just_key and prebuilt->keep_other_fields_on_keyread. Revision r1496: ha_innobase::extra(): Replace references to prebuilt->trx with thd_to_trx(ha_thd()), in order to avoid potential memory corruption. Revision r1501: Fix Bug#21293: Consider transactions that had edited non-transactional tables heavier than ones that had not. This helps killing the "right" transaction in case of a deadlock. Approved by: Heikki Revision r1513: Split ut_a(a && b [&& c...]); into separate ut_a(a); ut_a(b); [ut_a(c); ...]. This makes it possible to see which expression was false by looking at the error message. Approved by: Marko Revision r1527: Cleanup in ha_innodb.cc: thd_is_replication_slave_thread(), thd_has_edited_nontrans_tables(): Remove blank line between the function comment and the function definition. There should be exactly one line between the return type and the function comment, and this line should be one of '', 'static', 'UNIV_INLINE', and 'extern "C"'. Revision r1538: Do not return error in ha_innobase::info if srv_force_recovery >= 4. This is to allow for normal processing of the query by MySQL instead of generating an error. Reviewed by: Heikki Revision r1551: ha_innobase::innobase_read_and_init_auto_inc(): Remember and restore prebuilt->sql_stat_start. In an ALTER TABLE statement in the innodb_gis test, an ut_ad() assertion failed, because no IX lock had been acquired on the table, because prebuilt->sql_stat_start was inadvertently reset to FALSE, by this function. This function was called via ha_innobase::info() and mysql_prepare_alter_table(). storage/innobase/plug.in: Fixes after merging InnoDB snapshots. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead. storage/innobase/handler/ha_innodb.h: Fixes after merging InnoDB snapshots. Revision r1488: Make InnoDB pluggable. That is, merge the modifications from MySQL WL#2936 and adapt some things. Note that ha_innodb.cc depends on mysql_tmpfile() being declared in <mysql/plugin.h>. Until the function is declared there, you can uncomment the buggy definition of mysql_tmpfile in ha_innodb.cc. Remove storage/innobase/*/Makefile.am. The whole compilation is driven by storage/innobase/Makefile.am and storage/innobase/plug.in. plug.in: Declare InnoDB as a dynamic plugin. ha_innodb.h: Remove the declarations of many global variables. The variables are no longer directly referenced outside of storage/innobase. trx_t: Add the field trx->duplicates. trx_create(): Initialize the fields trx->active_trans and trx->duplicates. innobase_query_is_update(): Remove. Consult trx->duplicates instead.
1434 lines
37 KiB
C
1434 lines
37 KiB
C
/******************************************************
|
|
Transaction undo log record
|
|
|
|
(c) 1996 Innobase Oy
|
|
|
|
Created 3/26/1996 Heikki Tuuri
|
|
*******************************************************/
|
|
|
|
#include "trx0rec.h"
|
|
|
|
#ifdef UNIV_NONINL
|
|
#include "trx0rec.ic"
|
|
#endif
|
|
|
|
#include "fsp0fsp.h"
|
|
#include "mach0data.h"
|
|
#include "trx0rseg.h"
|
|
#include "trx0trx.h"
|
|
#include "trx0undo.h"
|
|
#include "dict0dict.h"
|
|
#include "ut0mem.h"
|
|
#include "row0upd.h"
|
|
#include "que0que.h"
|
|
#include "trx0purge.h"
|
|
#include "row0row.h"
|
|
|
|
/*=========== UNDO LOG RECORD CREATION AND DECODING ====================*/
|
|
|
|
/**************************************************************************
|
|
Writes the mtr log entry of the inserted undo log record on the undo log
|
|
page. */
|
|
UNIV_INLINE
|
|
void
|
|
trx_undof_page_add_undo_rec_log(
|
|
/*============================*/
|
|
page_t* undo_page, /* in: undo log page */
|
|
ulint old_free, /* in: start offset of the inserted entry */
|
|
ulint new_free, /* in: end offset of the entry */
|
|
mtr_t* mtr) /* in: mtr */
|
|
{
|
|
byte* log_ptr;
|
|
const byte* log_end;
|
|
ulint len;
|
|
|
|
log_ptr = mlog_open(mtr, 11 + 13 + MLOG_BUF_MARGIN);
|
|
|
|
if (log_ptr == NULL) {
|
|
|
|
return;
|
|
}
|
|
|
|
log_end = &log_ptr[11 + 13 + MLOG_BUF_MARGIN];
|
|
log_ptr = mlog_write_initial_log_record_fast(
|
|
undo_page, MLOG_UNDO_INSERT, log_ptr, mtr);
|
|
len = new_free - old_free - 4;
|
|
|
|
mach_write_to_2(log_ptr, len);
|
|
log_ptr += 2;
|
|
|
|
if (log_ptr + len <= log_end) {
|
|
memcpy(log_ptr, undo_page + old_free + 2, len);
|
|
mlog_close(mtr, log_ptr + len);
|
|
} else {
|
|
mlog_close(mtr, log_ptr);
|
|
mlog_catenate_string(mtr, undo_page + old_free + 2, len);
|
|
}
|
|
}
|
|
|
|
/***************************************************************
|
|
Parses a redo log record of adding an undo log record. */
|
|
|
|
byte*
|
|
trx_undo_parse_add_undo_rec(
|
|
/*========================*/
|
|
/* out: end of log record or NULL */
|
|
byte* ptr, /* in: buffer */
|
|
byte* end_ptr,/* in: buffer end */
|
|
page_t* page) /* in: page or NULL */
|
|
{
|
|
ulint len;
|
|
byte* rec;
|
|
ulint first_free;
|
|
|
|
if (end_ptr < ptr + 2) {
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
len = mach_read_from_2(ptr);
|
|
ptr += 2;
|
|
|
|
if (end_ptr < ptr + len) {
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
if (page == NULL) {
|
|
|
|
return(ptr + len);
|
|
}
|
|
|
|
first_free = mach_read_from_2(page + TRX_UNDO_PAGE_HDR
|
|
+ TRX_UNDO_PAGE_FREE);
|
|
rec = page + first_free;
|
|
|
|
mach_write_to_2(rec, first_free + 4 + len);
|
|
mach_write_to_2(rec + 2 + len, first_free);
|
|
|
|
mach_write_to_2(page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE,
|
|
first_free + 4 + len);
|
|
ut_memcpy(rec + 2, ptr, len);
|
|
|
|
return(ptr + len);
|
|
}
|
|
|
|
/**************************************************************************
|
|
Calculates the free space left for extending an undo log record. */
|
|
UNIV_INLINE
|
|
ulint
|
|
trx_undo_left(
|
|
/*==========*/
|
|
/* out: bytes left */
|
|
page_t* page, /* in: undo log page */
|
|
byte* ptr) /* in: pointer to page */
|
|
{
|
|
/* The '- 10' is a safety margin, in case we have some small
|
|
calculation error below */
|
|
|
|
return(UNIV_PAGE_SIZE - (ptr - page) - 10 - FIL_PAGE_DATA_END);
|
|
}
|
|
|
|
/**************************************************************************
|
|
Reports in the undo log of an insert of a clustered index record. */
|
|
static
|
|
ulint
|
|
trx_undo_page_report_insert(
|
|
/*========================*/
|
|
/* out: offset of the inserted entry
|
|
on the page if succeed, 0 if fail */
|
|
page_t* undo_page, /* in: undo log page */
|
|
trx_t* trx, /* in: transaction */
|
|
dict_index_t* index, /* in: clustered index */
|
|
dtuple_t* clust_entry, /* in: index entry which will be
|
|
inserted to the clustered index */
|
|
mtr_t* mtr) /* in: mtr */
|
|
{
|
|
ulint first_free;
|
|
byte* ptr;
|
|
ulint len;
|
|
dfield_t* field;
|
|
ulint flen;
|
|
ulint i;
|
|
|
|
ut_ad(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR
|
|
+ TRX_UNDO_PAGE_TYPE) == TRX_UNDO_INSERT);
|
|
|
|
first_free = mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR
|
|
+ TRX_UNDO_PAGE_FREE);
|
|
ptr = undo_page + first_free;
|
|
|
|
ut_ad(first_free <= UNIV_PAGE_SIZE);
|
|
|
|
if (trx_undo_left(undo_page, ptr) < 30) {
|
|
|
|
/* NOTE: the value 30 must be big enough such that the general
|
|
fields written below fit on the undo log page */
|
|
|
|
return(0);
|
|
}
|
|
|
|
/* Reserve 2 bytes for the pointer to the next undo log record */
|
|
ptr += 2;
|
|
|
|
/* Store first some general parameters to the undo log */
|
|
mach_write_to_1(ptr, TRX_UNDO_INSERT_REC);
|
|
ptr++;
|
|
|
|
len = mach_dulint_write_much_compressed(ptr, trx->undo_no);
|
|
ptr += len;
|
|
|
|
len = mach_dulint_write_much_compressed(ptr, (index->table)->id);
|
|
ptr += len;
|
|
/*----------------------------------------*/
|
|
/* Store then the fields required to uniquely determine the record
|
|
to be inserted in the clustered index */
|
|
|
|
for (i = 0; i < dict_index_get_n_unique(index); i++) {
|
|
|
|
field = dtuple_get_nth_field(clust_entry, i);
|
|
|
|
flen = dfield_get_len(field);
|
|
|
|
if (trx_undo_left(undo_page, ptr) < 5) {
|
|
|
|
return(0);
|
|
}
|
|
|
|
len = mach_write_compressed(ptr, flen);
|
|
ptr += len;
|
|
|
|
if (flen != UNIV_SQL_NULL) {
|
|
if (trx_undo_left(undo_page, ptr) < flen) {
|
|
|
|
return(0);
|
|
}
|
|
|
|
ut_memcpy(ptr, dfield_get_data(field), flen);
|
|
ptr += flen;
|
|
}
|
|
}
|
|
|
|
if (trx_undo_left(undo_page, ptr) < 2) {
|
|
|
|
return(0);
|
|
}
|
|
|
|
/*----------------------------------------*/
|
|
/* Write pointers to the previous and the next undo log records */
|
|
|
|
if (trx_undo_left(undo_page, ptr) < 2) {
|
|
|
|
return(0);
|
|
}
|
|
|
|
mach_write_to_2(ptr, first_free);
|
|
ptr += 2;
|
|
|
|
mach_write_to_2(undo_page + first_free, ptr - undo_page);
|
|
|
|
mach_write_to_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE,
|
|
ptr - undo_page);
|
|
|
|
/* Write the log entry to the REDO log of this change in the UNDO
|
|
log */
|
|
trx_undof_page_add_undo_rec_log(undo_page, first_free,
|
|
ptr - undo_page, mtr);
|
|
return(first_free);
|
|
}
|
|
|
|
/**************************************************************************
|
|
Reads from an undo log record the general parameters. */
|
|
|
|
byte*
|
|
trx_undo_rec_get_pars(
|
|
/*==================*/
|
|
/* out: remaining part of undo log
|
|
record after reading these values */
|
|
trx_undo_rec_t* undo_rec, /* in: undo log record */
|
|
ulint* type, /* out: undo record type:
|
|
TRX_UNDO_INSERT_REC, ... */
|
|
ulint* cmpl_info, /* out: compiler info, relevant only
|
|
for update type records */
|
|
ibool* updated_extern, /* out: TRUE if we updated an
|
|
externally stored fild */
|
|
dulint* undo_no, /* out: undo log record number */
|
|
dulint* table_id) /* out: table id */
|
|
{
|
|
byte* ptr;
|
|
ulint len;
|
|
ulint type_cmpl;
|
|
|
|
ptr = undo_rec + 2;
|
|
|
|
type_cmpl = mach_read_from_1(ptr);
|
|
ptr++;
|
|
|
|
if (type_cmpl & TRX_UNDO_UPD_EXTERN) {
|
|
*updated_extern = TRUE;
|
|
type_cmpl -= TRX_UNDO_UPD_EXTERN;
|
|
} else {
|
|
*updated_extern = FALSE;
|
|
}
|
|
|
|
*type = type_cmpl & (TRX_UNDO_CMPL_INFO_MULT - 1);
|
|
*cmpl_info = type_cmpl / TRX_UNDO_CMPL_INFO_MULT;
|
|
|
|
*undo_no = mach_dulint_read_much_compressed(ptr);
|
|
len = mach_dulint_get_much_compressed_size(*undo_no);
|
|
ptr += len;
|
|
|
|
*table_id = mach_dulint_read_much_compressed(ptr);
|
|
len = mach_dulint_get_much_compressed_size(*table_id);
|
|
ptr += len;
|
|
|
|
return(ptr);
|
|
}
|
|
|
|
/**************************************************************************
|
|
Reads from an undo log record a stored column value. */
|
|
static
|
|
byte*
|
|
trx_undo_rec_get_col_val(
|
|
/*=====================*/
|
|
/* out: remaining part of undo log record after
|
|
reading these values */
|
|
byte* ptr, /* in: pointer to remaining part of undo log record */
|
|
byte** field, /* out: pointer to stored field */
|
|
ulint* len) /* out: length of the field, or UNIV_SQL_NULL */
|
|
{
|
|
*len = mach_read_compressed(ptr);
|
|
ptr += mach_get_compressed_size(*len);
|
|
|
|
*field = ptr;
|
|
|
|
if (*len != UNIV_SQL_NULL) {
|
|
if (*len >= UNIV_EXTERN_STORAGE_FIELD) {
|
|
ptr += (*len - UNIV_EXTERN_STORAGE_FIELD);
|
|
} else {
|
|
ptr += *len;
|
|
}
|
|
}
|
|
|
|
return(ptr);
|
|
}
|
|
|
|
/***********************************************************************
|
|
Builds a row reference from an undo log record. */
|
|
|
|
byte*
|
|
trx_undo_rec_get_row_ref(
|
|
/*=====================*/
|
|
/* out: pointer to remaining part of undo
|
|
record */
|
|
byte* ptr, /* in: remaining part of a copy of an undo log
|
|
record, at the start of the row reference;
|
|
NOTE that this copy of the undo log record must
|
|
be preserved as long as the row reference is
|
|
used, as we do NOT copy the data in the
|
|
record! */
|
|
dict_index_t* index, /* in: clustered index */
|
|
dtuple_t** ref, /* out, own: row reference */
|
|
mem_heap_t* heap) /* in: memory heap from which the memory
|
|
needed is allocated */
|
|
{
|
|
dfield_t* dfield;
|
|
byte* field;
|
|
ulint len;
|
|
ulint ref_len;
|
|
ulint i;
|
|
|
|
ut_ad(index && ptr && ref && heap);
|
|
ut_a(index->type & DICT_CLUSTERED);
|
|
|
|
ref_len = dict_index_get_n_unique(index);
|
|
|
|
*ref = dtuple_create(heap, ref_len);
|
|
|
|
dict_index_copy_types(*ref, index, ref_len);
|
|
|
|
for (i = 0; i < ref_len; i++) {
|
|
dfield = dtuple_get_nth_field(*ref, i);
|
|
|
|
ptr = trx_undo_rec_get_col_val(ptr, &field, &len);
|
|
|
|
dfield_set_data(dfield, field, len);
|
|
}
|
|
|
|
return(ptr);
|
|
}
|
|
|
|
/***********************************************************************
|
|
Skips a row reference from an undo log record. */
|
|
|
|
byte*
|
|
trx_undo_rec_skip_row_ref(
|
|
/*======================*/
|
|
/* out: pointer to remaining part of undo
|
|
record */
|
|
byte* ptr, /* in: remaining part in update undo log
|
|
record, at the start of the row reference */
|
|
dict_index_t* index) /* in: clustered index */
|
|
{
|
|
byte* field;
|
|
ulint len;
|
|
ulint ref_len;
|
|
ulint i;
|
|
|
|
ut_ad(index && ptr);
|
|
ut_a(index->type & DICT_CLUSTERED);
|
|
|
|
ref_len = dict_index_get_n_unique(index);
|
|
|
|
for (i = 0; i < ref_len; i++) {
|
|
ptr = trx_undo_rec_get_col_val(ptr, &field, &len);
|
|
}
|
|
|
|
return(ptr);
|
|
}
|
|
|
|
/**************************************************************************
|
|
Reports in the undo log of an update or delete marking of a clustered index
|
|
record. */
|
|
static
|
|
ulint
|
|
trx_undo_page_report_modify(
|
|
/*========================*/
|
|
/* out: byte offset of the inserted
|
|
undo log entry on the page if succeed,
|
|
0 if fail */
|
|
page_t* undo_page, /* in: undo log page */
|
|
trx_t* trx, /* in: transaction */
|
|
dict_index_t* index, /* in: clustered index where update or
|
|
delete marking is done */
|
|
rec_t* rec, /* in: clustered index record which
|
|
has NOT yet been modified */
|
|
const ulint* offsets, /* in: rec_get_offsets(rec, index) */
|
|
upd_t* update, /* in: update vector which tells the
|
|
columns to be updated; in the case of
|
|
a delete, this should be set to NULL */
|
|
ulint cmpl_info, /* in: compiler info on secondary
|
|
index updates */
|
|
mtr_t* mtr) /* in: mtr */
|
|
{
|
|
dict_table_t* table;
|
|
upd_field_t* upd_field;
|
|
ulint first_free;
|
|
byte* ptr;
|
|
ulint len;
|
|
byte* field;
|
|
ulint flen;
|
|
ulint pos;
|
|
dulint roll_ptr;
|
|
dulint trx_id;
|
|
ulint bits;
|
|
ulint col_no;
|
|
byte* old_ptr;
|
|
ulint type_cmpl;
|
|
byte* type_cmpl_ptr;
|
|
ulint i;
|
|
|
|
ut_a(index->type & DICT_CLUSTERED);
|
|
ut_ad(rec_offs_validate(rec, index, offsets));
|
|
ut_ad(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR
|
|
+ TRX_UNDO_PAGE_TYPE) == TRX_UNDO_UPDATE);
|
|
table = index->table;
|
|
|
|
first_free = mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR
|
|
+ TRX_UNDO_PAGE_FREE);
|
|
ptr = undo_page + first_free;
|
|
|
|
ut_ad(first_free <= UNIV_PAGE_SIZE);
|
|
|
|
if (trx_undo_left(undo_page, ptr) < 50) {
|
|
|
|
/* NOTE: the value 50 must be big enough so that the general
|
|
fields written below fit on the undo log page */
|
|
|
|
return(0);
|
|
}
|
|
|
|
/* Reserve 2 bytes for the pointer to the next undo log record */
|
|
ptr += 2;
|
|
|
|
/* Store first some general parameters to the undo log */
|
|
|
|
if (update) {
|
|
if (rec_get_deleted_flag(rec, dict_table_is_comp(table))) {
|
|
type_cmpl = TRX_UNDO_UPD_DEL_REC;
|
|
} else {
|
|
type_cmpl = TRX_UNDO_UPD_EXIST_REC;
|
|
}
|
|
} else {
|
|
type_cmpl = TRX_UNDO_DEL_MARK_REC;
|
|
}
|
|
|
|
type_cmpl = type_cmpl | (cmpl_info * TRX_UNDO_CMPL_INFO_MULT);
|
|
|
|
mach_write_to_1(ptr, type_cmpl);
|
|
|
|
type_cmpl_ptr = ptr;
|
|
|
|
ptr++;
|
|
len = mach_dulint_write_much_compressed(ptr, trx->undo_no);
|
|
ptr += len;
|
|
|
|
len = mach_dulint_write_much_compressed(ptr, table->id);
|
|
ptr += len;
|
|
|
|
/*----------------------------------------*/
|
|
/* Store the state of the info bits */
|
|
|
|
bits = rec_get_info_bits(rec, dict_table_is_comp(table));
|
|
mach_write_to_1(ptr, bits);
|
|
ptr += 1;
|
|
|
|
/* Store the values of the system columns */
|
|
field = rec_get_nth_field(rec, offsets,
|
|
dict_index_get_sys_col_pos(
|
|
index, DATA_TRX_ID), &len);
|
|
ut_ad(len == DATA_TRX_ID_LEN);
|
|
trx_id = trx_read_trx_id(field);
|
|
field = rec_get_nth_field(rec, offsets,
|
|
dict_index_get_sys_col_pos(
|
|
index, DATA_ROLL_PTR), &len);
|
|
ut_ad(len == DATA_ROLL_PTR_LEN);
|
|
roll_ptr = trx_read_roll_ptr(field);
|
|
|
|
len = mach_dulint_write_compressed(ptr, trx_id);
|
|
ptr += len;
|
|
|
|
len = mach_dulint_write_compressed(ptr, roll_ptr);
|
|
ptr += len;
|
|
|
|
/*----------------------------------------*/
|
|
/* Store then the fields required to uniquely determine the
|
|
record which will be modified in the clustered index */
|
|
|
|
for (i = 0; i < dict_index_get_n_unique(index); i++) {
|
|
|
|
field = rec_get_nth_field(rec, offsets, i, &flen);
|
|
|
|
if (trx_undo_left(undo_page, ptr) < 4) {
|
|
|
|
return(0);
|
|
}
|
|
|
|
len = mach_write_compressed(ptr, flen);
|
|
ptr += len;
|
|
|
|
if (flen != UNIV_SQL_NULL) {
|
|
if (trx_undo_left(undo_page, ptr) < flen) {
|
|
|
|
return(0);
|
|
}
|
|
|
|
ut_memcpy(ptr, field, flen);
|
|
ptr += flen;
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------*/
|
|
/* Save to the undo log the old values of the columns to be updated. */
|
|
|
|
if (update) {
|
|
if (trx_undo_left(undo_page, ptr) < 5) {
|
|
|
|
return(0);
|
|
}
|
|
|
|
len = mach_write_compressed(ptr, upd_get_n_fields(update));
|
|
ptr += len;
|
|
|
|
for (i = 0; i < upd_get_n_fields(update); i++) {
|
|
|
|
upd_field = upd_get_nth_field(update, i);
|
|
pos = upd_field->field_no;
|
|
|
|
/* Write field number to undo log */
|
|
if (trx_undo_left(undo_page, ptr) < 5) {
|
|
|
|
return(0);
|
|
}
|
|
|
|
len = mach_write_compressed(ptr, pos);
|
|
ptr += len;
|
|
|
|
/* Save the old value of field */
|
|
field = rec_get_nth_field(rec, offsets, pos, &flen);
|
|
|
|
if (trx_undo_left(undo_page, ptr) < 5) {
|
|
|
|
return(0);
|
|
}
|
|
|
|
if (rec_offs_nth_extern(offsets, pos)) {
|
|
/* If a field has external storage, we add
|
|
to flen the flag */
|
|
|
|
len = mach_write_compressed(
|
|
ptr,
|
|
UNIV_EXTERN_STORAGE_FIELD + flen);
|
|
|
|
/* Notify purge that it eventually has to
|
|
free the old externally stored field */
|
|
|
|
trx->update_undo->del_marks = TRUE;
|
|
|
|
*type_cmpl_ptr = *type_cmpl_ptr
|
|
| TRX_UNDO_UPD_EXTERN;
|
|
} else {
|
|
len = mach_write_compressed(ptr, flen);
|
|
}
|
|
|
|
ptr += len;
|
|
|
|
if (flen != UNIV_SQL_NULL) {
|
|
if (trx_undo_left(undo_page, ptr) < flen) {
|
|
|
|
return(0);
|
|
}
|
|
|
|
ut_memcpy(ptr, field, flen);
|
|
ptr += flen;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------*/
|
|
/* In the case of a delete marking, and also in the case of an update
|
|
where any ordering field of any index changes, store the values of all
|
|
columns which occur as ordering fields in any index. This info is used
|
|
in the purge of old versions where we use it to build and search the
|
|
delete marked index records, to look if we can remove them from the
|
|
index tree. Note that starting from 4.0.14 also externally stored
|
|
fields can be ordering in some index. But we always store at least
|
|
384 first bytes locally to the clustered index record, which means
|
|
we can construct the column prefix fields in the index from the
|
|
stored data. */
|
|
|
|
if (!update || !(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
|
|
|
|
trx->update_undo->del_marks = TRUE;
|
|
|
|
if (trx_undo_left(undo_page, ptr) < 5) {
|
|
|
|
return(0);
|
|
}
|
|
|
|
old_ptr = ptr;
|
|
|
|
/* Reserve 2 bytes to write the number of bytes the stored
|
|
fields take in this undo record */
|
|
|
|
ptr += 2;
|
|
|
|
for (col_no = 0; col_no < dict_table_get_n_cols(table);
|
|
col_no++) {
|
|
|
|
const dict_col_t* col
|
|
= dict_table_get_nth_col(table, col_no);
|
|
|
|
if (col->ord_part > 0) {
|
|
|
|
pos = dict_index_get_nth_col_pos(index,
|
|
col_no);
|
|
|
|
/* Write field number to undo log */
|
|
if (trx_undo_left(undo_page, ptr) < 5) {
|
|
|
|
return(0);
|
|
}
|
|
|
|
len = mach_write_compressed(ptr, pos);
|
|
ptr += len;
|
|
|
|
/* Save the old value of field */
|
|
field = rec_get_nth_field(rec, offsets, pos,
|
|
&flen);
|
|
|
|
if (trx_undo_left(undo_page, ptr) < 5) {
|
|
|
|
return(0);
|
|
}
|
|
|
|
len = mach_write_compressed(ptr, flen);
|
|
ptr += len;
|
|
|
|
if (flen != UNIV_SQL_NULL) {
|
|
if (trx_undo_left(undo_page, ptr)
|
|
< flen) {
|
|
|
|
return(0);
|
|
}
|
|
|
|
ut_memcpy(ptr, field, flen);
|
|
ptr += flen;
|
|
}
|
|
}
|
|
}
|
|
|
|
mach_write_to_2(old_ptr, ptr - old_ptr);
|
|
}
|
|
|
|
/*----------------------------------------*/
|
|
/* Write pointers to the previous and the next undo log records */
|
|
if (trx_undo_left(undo_page, ptr) < 2) {
|
|
|
|
return(0);
|
|
}
|
|
|
|
mach_write_to_2(ptr, first_free);
|
|
ptr += 2;
|
|
mach_write_to_2(undo_page + first_free, ptr - undo_page);
|
|
|
|
mach_write_to_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE,
|
|
ptr - undo_page);
|
|
|
|
/* Write to the REDO log about this change in the UNDO log */
|
|
|
|
trx_undof_page_add_undo_rec_log(undo_page, first_free,
|
|
ptr - undo_page, mtr);
|
|
return(first_free);
|
|
}
|
|
|
|
/**************************************************************************
|
|
Reads from an undo log update record the system field values of the old
|
|
version. */
|
|
|
|
byte*
|
|
trx_undo_update_rec_get_sys_cols(
|
|
/*=============================*/
|
|
/* out: remaining part of undo log
|
|
record after reading these values */
|
|
byte* ptr, /* in: remaining part of undo log
|
|
record after reading general
|
|
parameters */
|
|
dulint* trx_id, /* out: trx id */
|
|
dulint* roll_ptr, /* out: roll ptr */
|
|
ulint* info_bits) /* out: info bits state */
|
|
{
|
|
ulint len;
|
|
|
|
/* Read the state of the info bits */
|
|
*info_bits = mach_read_from_1(ptr);
|
|
ptr += 1;
|
|
|
|
/* Read the values of the system columns */
|
|
|
|
*trx_id = mach_dulint_read_compressed(ptr);
|
|
len = mach_dulint_get_compressed_size(*trx_id);
|
|
ptr += len;
|
|
|
|
*roll_ptr = mach_dulint_read_compressed(ptr);
|
|
len = mach_dulint_get_compressed_size(*roll_ptr);
|
|
ptr += len;
|
|
|
|
return(ptr);
|
|
}
|
|
|
|
/**************************************************************************
|
|
Reads from an update undo log record the number of updated fields. */
|
|
UNIV_INLINE
|
|
byte*
|
|
trx_undo_update_rec_get_n_upd_fields(
|
|
/*=================================*/
|
|
/* out: remaining part of undo log record after
|
|
reading this value */
|
|
byte* ptr, /* in: pointer to remaining part of undo log record */
|
|
ulint* n) /* out: number of fields */
|
|
{
|
|
*n = mach_read_compressed(ptr);
|
|
ptr += mach_get_compressed_size(*n);
|
|
|
|
return(ptr);
|
|
}
|
|
|
|
/**************************************************************************
|
|
Reads from an update undo log record a stored field number. */
|
|
UNIV_INLINE
|
|
byte*
|
|
trx_undo_update_rec_get_field_no(
|
|
/*=============================*/
|
|
/* out: remaining part of undo log record after
|
|
reading this value */
|
|
byte* ptr, /* in: pointer to remaining part of undo log record */
|
|
ulint* field_no)/* out: field number */
|
|
{
|
|
*field_no = mach_read_compressed(ptr);
|
|
ptr += mach_get_compressed_size(*field_no);
|
|
|
|
return(ptr);
|
|
}
|
|
|
|
/***********************************************************************
|
|
Builds an update vector based on a remaining part of an undo log record. */
|
|
|
|
byte*
|
|
trx_undo_update_rec_get_update(
|
|
/*===========================*/
|
|
/* out: remaining part of the record,
|
|
NULL if an error detected, which means that
|
|
the record is corrupted */
|
|
byte* ptr, /* in: remaining part in update undo log
|
|
record, after reading the row reference
|
|
NOTE that this copy of the undo log record must
|
|
be preserved as long as the update vector is
|
|
used, as we do NOT copy the data in the
|
|
record! */
|
|
dict_index_t* index, /* in: clustered index */
|
|
ulint type, /* in: TRX_UNDO_UPD_EXIST_REC,
|
|
TRX_UNDO_UPD_DEL_REC, or
|
|
TRX_UNDO_DEL_MARK_REC; in the last case,
|
|
only trx id and roll ptr fields are added to
|
|
the update vector */
|
|
dulint trx_id, /* in: transaction id from this undo record */
|
|
dulint roll_ptr,/* in: roll pointer from this undo record */
|
|
ulint info_bits,/* in: info bits from this undo record */
|
|
trx_t* trx, /* in: transaction */
|
|
mem_heap_t* heap, /* in: memory heap from which the memory
|
|
needed is allocated */
|
|
upd_t** upd) /* out, own: update vector */
|
|
{
|
|
upd_field_t* upd_field;
|
|
upd_t* update;
|
|
ulint n_fields;
|
|
byte* buf;
|
|
byte* field;
|
|
ulint len;
|
|
ulint field_no;
|
|
ulint i;
|
|
|
|
ut_a(index->type & DICT_CLUSTERED);
|
|
|
|
if (type != TRX_UNDO_DEL_MARK_REC) {
|
|
ptr = trx_undo_update_rec_get_n_upd_fields(ptr, &n_fields);
|
|
} else {
|
|
n_fields = 0;
|
|
}
|
|
|
|
update = upd_create(n_fields + 2, heap);
|
|
|
|
update->info_bits = info_bits;
|
|
|
|
/* Store first trx id and roll ptr to update vector */
|
|
|
|
upd_field = upd_get_nth_field(update, n_fields);
|
|
buf = mem_heap_alloc(heap, DATA_TRX_ID_LEN);
|
|
trx_write_trx_id(buf, trx_id);
|
|
|
|
upd_field_set_field_no(upd_field,
|
|
dict_index_get_sys_col_pos(index, DATA_TRX_ID),
|
|
index, trx);
|
|
dfield_set_data(&(upd_field->new_val), buf, DATA_TRX_ID_LEN);
|
|
|
|
upd_field = upd_get_nth_field(update, n_fields + 1);
|
|
buf = mem_heap_alloc(heap, DATA_ROLL_PTR_LEN);
|
|
trx_write_roll_ptr(buf, roll_ptr);
|
|
|
|
upd_field_set_field_no(
|
|
upd_field, dict_index_get_sys_col_pos(index, DATA_ROLL_PTR),
|
|
index, trx);
|
|
dfield_set_data(&(upd_field->new_val), buf, DATA_ROLL_PTR_LEN);
|
|
|
|
/* Store then the updated ordinary columns to the update vector */
|
|
|
|
for (i = 0; i < n_fields; i++) {
|
|
|
|
ptr = trx_undo_update_rec_get_field_no(ptr, &field_no);
|
|
|
|
if (field_no >= dict_index_get_n_fields(index)) {
|
|
fprintf(stderr,
|
|
"InnoDB: Error: trying to access"
|
|
" update undo rec field %lu in ",
|
|
(ulong) field_no);
|
|
dict_index_name_print(stderr, trx, index);
|
|
fprintf(stderr, "\n"
|
|
"InnoDB: but index has only %lu fields\n"
|
|
"InnoDB: Submit a detailed bug report"
|
|
" to http://bugs.mysql.com\n"
|
|
"InnoDB: Run also CHECK TABLE ",
|
|
(ulong) dict_index_get_n_fields(index));
|
|
ut_print_name(stderr, trx, TRUE, index->table_name);
|
|
fprintf(stderr, "\n"
|
|
"InnoDB: n_fields = %lu, i = %lu, ptr %p\n",
|
|
(ulong) n_fields, (ulong) i, ptr);
|
|
return(NULL);
|
|
}
|
|
|
|
ptr = trx_undo_rec_get_col_val(ptr, &field, &len);
|
|
|
|
upd_field = upd_get_nth_field(update, i);
|
|
|
|
upd_field_set_field_no(upd_field, field_no, index, trx);
|
|
|
|
if (len != UNIV_SQL_NULL && len >= UNIV_EXTERN_STORAGE_FIELD) {
|
|
|
|
upd_field->extern_storage = TRUE;
|
|
|
|
len -= UNIV_EXTERN_STORAGE_FIELD;
|
|
}
|
|
|
|
dfield_set_data(&(upd_field->new_val), field, len);
|
|
}
|
|
|
|
*upd = update;
|
|
|
|
return(ptr);
|
|
}
|
|
|
|
/***********************************************************************
|
|
Builds a partial row from an update undo log record. It contains the
|
|
columns which occur as ordering in any index of the table. */
|
|
|
|
byte*
|
|
trx_undo_rec_get_partial_row(
|
|
/*=========================*/
|
|
/* out: pointer to remaining part of undo
|
|
record */
|
|
byte* ptr, /* in: remaining part in update undo log
|
|
record of a suitable type, at the start of
|
|
the stored index columns;
|
|
NOTE that this copy of the undo log record must
|
|
be preserved as long as the partial row is
|
|
used, as we do NOT copy the data in the
|
|
record! */
|
|
dict_index_t* index, /* in: clustered index */
|
|
dtuple_t** row, /* out, own: partial row */
|
|
mem_heap_t* heap) /* in: memory heap from which the memory
|
|
needed is allocated */
|
|
{
|
|
dfield_t* dfield;
|
|
byte* field;
|
|
ulint len;
|
|
ulint field_no;
|
|
ulint col_no;
|
|
ulint row_len;
|
|
ulint total_len;
|
|
byte* start_ptr;
|
|
ulint i;
|
|
|
|
ut_ad(index && ptr && row && heap);
|
|
|
|
row_len = dict_table_get_n_cols(index->table);
|
|
|
|
*row = dtuple_create(heap, row_len);
|
|
|
|
dict_table_copy_types(*row, index->table);
|
|
|
|
start_ptr = ptr;
|
|
|
|
total_len = mach_read_from_2(ptr);
|
|
ptr += 2;
|
|
|
|
for (i = 0;; i++) {
|
|
|
|
if (ptr == start_ptr + total_len) {
|
|
|
|
break;
|
|
}
|
|
|
|
ptr = trx_undo_update_rec_get_field_no(ptr, &field_no);
|
|
|
|
col_no = dict_index_get_nth_col_no(index, field_no);
|
|
|
|
ptr = trx_undo_rec_get_col_val(ptr, &field, &len);
|
|
|
|
dfield = dtuple_get_nth_field(*row, col_no);
|
|
|
|
dfield_set_data(dfield, field, len);
|
|
}
|
|
|
|
return(ptr);
|
|
}
|
|
|
|
/***************************************************************************
|
|
Erases the unused undo log page end. */
|
|
static
|
|
void
|
|
trx_undo_erase_page_end(
|
|
/*====================*/
|
|
page_t* undo_page, /* in: undo page whose end to erase */
|
|
mtr_t* mtr) /* in: mtr */
|
|
{
|
|
ulint first_free;
|
|
|
|
first_free = mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR
|
|
+ TRX_UNDO_PAGE_FREE);
|
|
memset(undo_page + first_free, 0xff,
|
|
(UNIV_PAGE_SIZE - FIL_PAGE_DATA_END) - first_free);
|
|
|
|
mlog_write_initial_log_record(undo_page, MLOG_UNDO_ERASE_END, mtr);
|
|
}
|
|
|
|
/***************************************************************
|
|
Parses a redo log record of erasing of an undo page end. */
|
|
|
|
byte*
|
|
trx_undo_parse_erase_page_end(
|
|
/*==========================*/
|
|
/* out: end of log record or NULL */
|
|
byte* ptr, /* in: buffer */
|
|
byte* end_ptr __attribute__((unused)), /* in: buffer end */
|
|
page_t* page, /* in: page or NULL */
|
|
mtr_t* mtr) /* in: mtr or NULL */
|
|
{
|
|
ut_ad(ptr && end_ptr);
|
|
|
|
if (page == NULL) {
|
|
|
|
return(ptr);
|
|
}
|
|
|
|
trx_undo_erase_page_end(page, mtr);
|
|
|
|
return(ptr);
|
|
}
|
|
|
|
/***************************************************************************
|
|
Writes information to an undo log about an insert, update, or a delete marking
|
|
of a clustered index record. This information is used in a rollback of the
|
|
transaction and in consistent reads that must look to the history of this
|
|
transaction. */
|
|
|
|
ulint
|
|
trx_undo_report_row_operation(
|
|
/*==========================*/
|
|
/* out: DB_SUCCESS or error code */
|
|
ulint flags, /* in: if BTR_NO_UNDO_LOG_FLAG bit is
|
|
set, does nothing */
|
|
ulint op_type, /* in: TRX_UNDO_INSERT_OP or
|
|
TRX_UNDO_MODIFY_OP */
|
|
que_thr_t* thr, /* in: query thread */
|
|
dict_index_t* index, /* in: clustered index */
|
|
dtuple_t* clust_entry, /* in: in the case of an insert,
|
|
index entry to insert into the
|
|
clustered index, otherwise NULL */
|
|
upd_t* update, /* in: in the case of an update,
|
|
the update vector, otherwise NULL */
|
|
ulint cmpl_info, /* in: compiler info on secondary
|
|
index updates */
|
|
rec_t* rec, /* in: in case of an update or delete
|
|
marking, the record in the clustered
|
|
index, otherwise NULL */
|
|
dulint* roll_ptr) /* out: rollback pointer to the
|
|
inserted undo log record,
|
|
ut_dulint_zero if BTR_NO_UNDO_LOG
|
|
flag was specified */
|
|
{
|
|
trx_t* trx;
|
|
trx_undo_t* undo;
|
|
page_t* undo_page;
|
|
ulint offset;
|
|
ulint page_no;
|
|
ibool is_insert;
|
|
trx_rseg_t* rseg;
|
|
mtr_t mtr;
|
|
ulint err = DB_SUCCESS;
|
|
mem_heap_t* heap = NULL;
|
|
ulint offsets_[REC_OFFS_NORMAL_SIZE];
|
|
ulint* offsets = offsets_;
|
|
*offsets_ = (sizeof offsets_) / sizeof *offsets_;
|
|
|
|
ut_a(index->type & DICT_CLUSTERED);
|
|
|
|
if (flags & BTR_NO_UNDO_LOG_FLAG) {
|
|
|
|
*roll_ptr = ut_dulint_zero;
|
|
|
|
return(err);
|
|
}
|
|
|
|
ut_ad(thr);
|
|
ut_ad((op_type != TRX_UNDO_INSERT_OP)
|
|
|| (clust_entry && !update && !rec));
|
|
|
|
trx = thr_get_trx(thr);
|
|
rseg = trx->rseg;
|
|
|
|
mutex_enter(&(trx->undo_mutex));
|
|
|
|
/* If the undo log is not assigned yet, assign one */
|
|
|
|
if (op_type == TRX_UNDO_INSERT_OP) {
|
|
|
|
if (trx->insert_undo == NULL) {
|
|
|
|
err = trx_undo_assign_undo(trx, TRX_UNDO_INSERT);
|
|
}
|
|
|
|
undo = trx->insert_undo;
|
|
is_insert = TRUE;
|
|
} else {
|
|
ut_ad(op_type == TRX_UNDO_MODIFY_OP);
|
|
|
|
if (trx->update_undo == NULL) {
|
|
|
|
err = trx_undo_assign_undo(trx, TRX_UNDO_UPDATE);
|
|
|
|
}
|
|
|
|
undo = trx->update_undo;
|
|
is_insert = FALSE;
|
|
}
|
|
|
|
if (err != DB_SUCCESS) {
|
|
/* Did not succeed: return the error encountered */
|
|
mutex_exit(&(trx->undo_mutex));
|
|
|
|
return(err);
|
|
}
|
|
|
|
page_no = undo->last_page_no;
|
|
|
|
mtr_start(&mtr);
|
|
|
|
for (;;) {
|
|
undo_page = buf_page_get_gen(undo->space, page_no,
|
|
RW_X_LATCH, undo->guess_page,
|
|
BUF_GET,
|
|
__FILE__, __LINE__,
|
|
&mtr);
|
|
|
|
#ifdef UNIV_SYNC_DEBUG
|
|
buf_page_dbg_add_level(undo_page, SYNC_TRX_UNDO_PAGE);
|
|
#endif /* UNIV_SYNC_DEBUG */
|
|
|
|
if (op_type == TRX_UNDO_INSERT_OP) {
|
|
offset = trx_undo_page_report_insert(
|
|
undo_page, trx, index, clust_entry, &mtr);
|
|
} else {
|
|
offsets = rec_get_offsets(rec, index, offsets,
|
|
ULINT_UNDEFINED, &heap);
|
|
offset = trx_undo_page_report_modify(
|
|
undo_page, trx, index, rec, offsets, update,
|
|
cmpl_info, &mtr);
|
|
}
|
|
|
|
if (offset == 0) {
|
|
/* The record did not fit on the page. We erase the
|
|
end segment of the undo log page and write a log
|
|
record of it: this is to ensure that in the debug
|
|
version the replicate page constructed using the log
|
|
records stays identical to the original page */
|
|
|
|
trx_undo_erase_page_end(undo_page, &mtr);
|
|
}
|
|
|
|
mtr_commit(&mtr);
|
|
|
|
if (offset != 0) {
|
|
/* Success */
|
|
|
|
break;
|
|
}
|
|
|
|
ut_ad(page_no == undo->last_page_no);
|
|
|
|
/* We have to extend the undo log by one page */
|
|
|
|
mtr_start(&mtr);
|
|
|
|
/* When we add a page to an undo log, this is analogous to
|
|
a pessimistic insert in a B-tree, and we must reserve the
|
|
counterpart of the tree latch, which is the rseg mutex. */
|
|
|
|
mutex_enter(&(rseg->mutex));
|
|
|
|
page_no = trx_undo_add_page(trx, undo, &mtr);
|
|
|
|
mutex_exit(&(rseg->mutex));
|
|
|
|
if (page_no == FIL_NULL) {
|
|
/* Did not succeed: out of space */
|
|
|
|
mutex_exit(&(trx->undo_mutex));
|
|
mtr_commit(&mtr);
|
|
if (UNIV_LIKELY_NULL(heap)) {
|
|
mem_heap_free(heap);
|
|
}
|
|
return(DB_OUT_OF_FILE_SPACE);
|
|
}
|
|
}
|
|
|
|
undo->empty = FALSE;
|
|
undo->top_page_no = page_no;
|
|
undo->top_offset = offset;
|
|
undo->top_undo_no = trx->undo_no;
|
|
undo->guess_page = undo_page;
|
|
|
|
UT_DULINT_INC(trx->undo_no);
|
|
|
|
mutex_exit(&(trx->undo_mutex));
|
|
|
|
*roll_ptr = trx_undo_build_roll_ptr(is_insert, rseg->id, page_no,
|
|
offset);
|
|
if (UNIV_LIKELY_NULL(heap)) {
|
|
mem_heap_free(heap);
|
|
}
|
|
return(err);
|
|
}
|
|
|
|
/*============== BUILDING PREVIOUS VERSION OF A RECORD ===============*/
|
|
|
|
/**********************************************************************
|
|
Copies an undo record to heap. This function can be called if we know that
|
|
the undo log record exists. */
|
|
|
|
trx_undo_rec_t*
|
|
trx_undo_get_undo_rec_low(
|
|
/*======================*/
|
|
/* out, own: copy of the record */
|
|
dulint roll_ptr, /* in: roll pointer to record */
|
|
mem_heap_t* heap) /* in: memory heap where copied */
|
|
{
|
|
trx_undo_rec_t* undo_rec;
|
|
ulint rseg_id;
|
|
ulint page_no;
|
|
ulint offset;
|
|
page_t* undo_page;
|
|
trx_rseg_t* rseg;
|
|
ibool is_insert;
|
|
mtr_t mtr;
|
|
|
|
trx_undo_decode_roll_ptr(roll_ptr, &is_insert, &rseg_id, &page_no,
|
|
&offset);
|
|
rseg = trx_rseg_get_on_id(rseg_id);
|
|
|
|
mtr_start(&mtr);
|
|
|
|
undo_page = trx_undo_page_get_s_latched(rseg->space, page_no, &mtr);
|
|
|
|
undo_rec = trx_undo_rec_copy(undo_page + offset, heap);
|
|
|
|
mtr_commit(&mtr);
|
|
|
|
return(undo_rec);
|
|
}
|
|
|
|
/**********************************************************************
|
|
Copies an undo record to heap. */
|
|
|
|
ulint
|
|
trx_undo_get_undo_rec(
|
|
/*==================*/
|
|
/* out: DB_SUCCESS, or
|
|
DB_MISSING_HISTORY if the undo log
|
|
has been truncated and we cannot
|
|
fetch the old version; NOTE: the
|
|
caller must have latches on the
|
|
clustered index page and purge_view */
|
|
dulint roll_ptr, /* in: roll pointer to record */
|
|
dulint trx_id, /* in: id of the trx that generated
|
|
the roll pointer: it points to an
|
|
undo log of this transaction */
|
|
trx_undo_rec_t** undo_rec, /* out, own: copy of the record */
|
|
mem_heap_t* heap) /* in: memory heap where copied */
|
|
{
|
|
#ifdef UNIV_SYNC_DEBUG
|
|
ut_ad(rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
|
|
#endif /* UNIV_SYNC_DEBUG */
|
|
|
|
if (!trx_purge_update_undo_must_exist(trx_id)) {
|
|
|
|
/* It may be that the necessary undo log has already been
|
|
deleted */
|
|
|
|
return(DB_MISSING_HISTORY);
|
|
}
|
|
|
|
*undo_rec = trx_undo_get_undo_rec_low(roll_ptr, heap);
|
|
|
|
return(DB_SUCCESS);
|
|
}
|
|
|
|
/***********************************************************************
|
|
Build a previous version of a clustered index record. This function checks
|
|
that the caller has a latch on the index page of the clustered index record
|
|
and an s-latch on the purge_view. This guarantees that the stack of versions
|
|
is locked. */
|
|
|
|
ulint
|
|
trx_undo_prev_version_build(
|
|
/*========================*/
|
|
/* out: DB_SUCCESS, or DB_MISSING_HISTORY if
|
|
the previous version is not >= purge_view,
|
|
which means that it may have been removed,
|
|
DB_ERROR if corrupted record */
|
|
rec_t* index_rec,/* in: clustered index record in the
|
|
index tree */
|
|
mtr_t* index_mtr __attribute__((unused)),
|
|
/* in: mtr which contains the latch to
|
|
index_rec page and purge_view */
|
|
rec_t* rec, /* in: version of a clustered index record */
|
|
dict_index_t* index, /* in: clustered index */
|
|
ulint* offsets,/* in: rec_get_offsets(rec, index) */
|
|
mem_heap_t* heap, /* in: memory heap from which the memory
|
|
needed is allocated */
|
|
rec_t** old_vers)/* out, own: previous version, or NULL if
|
|
rec is the first inserted version, or if
|
|
history data has been deleted */
|
|
{
|
|
trx_undo_rec_t* undo_rec;
|
|
dtuple_t* entry;
|
|
dulint rec_trx_id;
|
|
ulint type;
|
|
dulint undo_no;
|
|
dulint table_id;
|
|
dulint trx_id;
|
|
dulint roll_ptr;
|
|
dulint old_roll_ptr;
|
|
upd_t* update;
|
|
byte* ptr;
|
|
ulint info_bits;
|
|
ulint cmpl_info;
|
|
ibool dummy_extern;
|
|
byte* buf;
|
|
ulint err;
|
|
#ifdef UNIV_SYNC_DEBUG
|
|
ut_ad(rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
|
|
#endif /* UNIV_SYNC_DEBUG */
|
|
ut_ad(mtr_memo_contains(index_mtr, buf_block_align(index_rec),
|
|
MTR_MEMO_PAGE_S_FIX)
|
|
|| mtr_memo_contains(index_mtr, buf_block_align(index_rec),
|
|
MTR_MEMO_PAGE_X_FIX));
|
|
ut_ad(rec_offs_validate(rec, index, offsets));
|
|
|
|
if (!(index->type & DICT_CLUSTERED)) {
|
|
fprintf(stderr, "InnoDB: Error: trying to access"
|
|
" update undo rec for non-clustered index %s\n"
|
|
"InnoDB: Submit a detailed bug report to"
|
|
" http://bugs.mysql.com\n"
|
|
"InnoDB: index record ", index->name);
|
|
rec_print(stderr, index_rec, index);
|
|
fputs("\n"
|
|
"InnoDB: record version ", stderr);
|
|
rec_print_new(stderr, rec, offsets);
|
|
putc('\n', stderr);
|
|
return(DB_ERROR);
|
|
}
|
|
|
|
roll_ptr = row_get_rec_roll_ptr(rec, index, offsets);
|
|
old_roll_ptr = roll_ptr;
|
|
|
|
*old_vers = NULL;
|
|
|
|
if (trx_undo_roll_ptr_is_insert(roll_ptr)) {
|
|
|
|
/* The record rec is the first inserted version */
|
|
|
|
return(DB_SUCCESS);
|
|
}
|
|
|
|
rec_trx_id = row_get_rec_trx_id(rec, index, offsets);
|
|
|
|
err = trx_undo_get_undo_rec(roll_ptr, rec_trx_id, &undo_rec, heap);
|
|
|
|
if (err != DB_SUCCESS) {
|
|
|
|
return(err);
|
|
}
|
|
|
|
ptr = trx_undo_rec_get_pars(undo_rec, &type, &cmpl_info,
|
|
&dummy_extern, &undo_no, &table_id);
|
|
|
|
ptr = trx_undo_update_rec_get_sys_cols(ptr, &trx_id, &roll_ptr,
|
|
&info_bits);
|
|
ptr = trx_undo_rec_skip_row_ref(ptr, index);
|
|
|
|
ptr = trx_undo_update_rec_get_update(ptr, index, type, trx_id,
|
|
roll_ptr, info_bits,
|
|
NULL, heap, &update);
|
|
|
|
if (ut_dulint_cmp(table_id, index->table->id) != 0) {
|
|
ptr = NULL;
|
|
|
|
fprintf(stderr,
|
|
"InnoDB: Error: trying to access update undo rec"
|
|
" for table %s\n"
|
|
"InnoDB: but the table id in the"
|
|
" undo record is wrong\n"
|
|
"InnoDB: Submit a detailed bug report"
|
|
" to http://bugs.mysql.com\n"
|
|
"InnoDB: Run also CHECK TABLE %s\n",
|
|
index->table_name, index->table_name);
|
|
}
|
|
|
|
if (ptr == NULL) {
|
|
/* The record was corrupted, return an error; these printfs
|
|
should catch an elusive bug in row_vers_old_has_index_entry */
|
|
|
|
fprintf(stderr,
|
|
"InnoDB: table %s, index %s, n_uniq %lu\n"
|
|
"InnoDB: undo rec address %p, type %lu cmpl_info %lu\n"
|
|
"InnoDB: undo rec table id %lu %lu,"
|
|
" index table id %lu %lu\n"
|
|
"InnoDB: dump of 150 bytes in undo rec: ",
|
|
index->table_name, index->name,
|
|
(ulong) dict_index_get_n_unique(index),
|
|
undo_rec, (ulong) type, (ulong) cmpl_info,
|
|
(ulong) ut_dulint_get_high(table_id),
|
|
(ulong) ut_dulint_get_low(table_id),
|
|
(ulong) ut_dulint_get_high(index->table->id),
|
|
(ulong) ut_dulint_get_low(index->table->id));
|
|
ut_print_buf(stderr, undo_rec, 150);
|
|
fputs("\n"
|
|
"InnoDB: index record ", stderr);
|
|
rec_print(stderr, index_rec, index);
|
|
fputs("\n"
|
|
"InnoDB: record version ", stderr);
|
|
rec_print_new(stderr, rec, offsets);
|
|
fprintf(stderr, "\n"
|
|
"InnoDB: Record trx id %lu %lu, update rec"
|
|
" trx id %lu %lu\n"
|
|
"InnoDB: Roll ptr in rec %lu %lu, in update rec"
|
|
" %lu %lu\n",
|
|
(ulong) ut_dulint_get_high(rec_trx_id),
|
|
(ulong) ut_dulint_get_low(rec_trx_id),
|
|
(ulong) ut_dulint_get_high(trx_id),
|
|
(ulong) ut_dulint_get_low(trx_id),
|
|
(ulong) ut_dulint_get_high(old_roll_ptr),
|
|
(ulong) ut_dulint_get_low(old_roll_ptr),
|
|
(ulong) ut_dulint_get_high(roll_ptr),
|
|
(ulong) ut_dulint_get_low(roll_ptr));
|
|
|
|
trx_purge_sys_print();
|
|
return(DB_ERROR);
|
|
}
|
|
|
|
if (row_upd_changes_field_size_or_external(index, offsets, update)) {
|
|
ulint* ext_vect;
|
|
ulint n_ext_vect;
|
|
|
|
/* We have to set the appropriate extern storage bits in the
|
|
old version of the record: the extern bits in rec for those
|
|
fields that update does NOT update, as well as the the bits for
|
|
those fields that update updates to become externally stored
|
|
fields. Store the info to ext_vect: */
|
|
|
|
ext_vect = mem_alloc(sizeof(ulint)
|
|
* rec_offs_n_fields(offsets));
|
|
n_ext_vect = btr_push_update_extern_fields(ext_vect, offsets,
|
|
update);
|
|
entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec,
|
|
heap);
|
|
row_upd_index_replace_new_col_vals(entry, index, update, heap);
|
|
|
|
buf = mem_heap_alloc(heap,
|
|
rec_get_converted_size(index, entry));
|
|
|
|
*old_vers = rec_convert_dtuple_to_rec(buf, index, entry);
|
|
|
|
/* Now set the extern bits in the old version of the record */
|
|
rec_set_field_extern_bits(*old_vers, index,
|
|
ext_vect, n_ext_vect, NULL);
|
|
mem_free(ext_vect);
|
|
} else {
|
|
buf = mem_heap_alloc(heap, rec_offs_size(offsets));
|
|
*old_vers = rec_copy(buf, rec, offsets);
|
|
rec_offs_make_valid(*old_vers, index, offsets);
|
|
row_upd_rec_in_place(*old_vers, offsets, update);
|
|
}
|
|
|
|
return(DB_SUCCESS);
|
|
}
|