From 2bedc3978b90bf5abe1029df393c63ced1849bed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 22 Sep 2016 16:32:26 +0300 Subject: MDEV-9931: InnoDB reads first page of every .ibd file at startup Analysis: By design InnoDB was reading first page of every .ibd file at startup to find out is tablespace encrypted or not. This is because tablespace could have been encrypted always, not encrypted newer or encrypted based on configuration and this information can be find realible only from first page of .ibd file. Fix: Do not read first page of every .ibd file at startup. Instead whenever tablespace is first time accedded we will read the first page to find necessary information about tablespace encryption status. TODO: Add support for SYS_TABLEOPTIONS where all table options encryption information included will be stored. --- storage/innobase/include/fil0crypt.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'storage/innobase/include/fil0crypt.h') diff --git a/storage/innobase/include/fil0crypt.h b/storage/innobase/include/fil0crypt.h index fdc413e7520..8ffa4e2073f 100644 --- a/storage/innobase/include/fil0crypt.h +++ b/storage/innobase/include/fil0crypt.h @@ -316,7 +316,8 @@ UNIV_INTERN void fil_space_crypt_mark_space_closing( /*===============================*/ - ulint space); /*!< in: tablespace id */ + ulint space, /*!< in: tablespace id */ + fil_space_crypt_t* crypt_data); /*!< in: crypt_data or NULL */ /********************************************************************* Wait for crypt threads to stop accessing space */ -- cgit v1.2.1 From 72cc73cea2e7071277b6a88bae0236cabf11788a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 13 Dec 2016 11:51:33 +0200 Subject: MDEV-10368: get_latest_version() called too often Reduce the number of calls to encryption_get_key_get_latest_version when doing key rotation with two different methods: (1) We need to fetch key information when tablespace not yet have a encryption information, invalid keys are handled now differently (see below). There was extra call to detect if key_id is not found on key rotation. (2) If key_id is not found from encryption plugin, do not try fetching new key_version for it as it will fail anyway. We store return value from encryption_get_key_get_latest_version call and if it returns ENCRYPTION_KEY_VERSION_INVALID there is no need to call it again. --- storage/innobase/include/fil0crypt.h | 114 ++++++++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 1 deletion(-) (limited to 'storage/innobase/include/fil0crypt.h') diff --git a/storage/innobase/include/fil0crypt.h b/storage/innobase/include/fil0crypt.h index 8ffa4e2073f..8bb0ce65a6b 100644 --- a/storage/innobase/include/fil0crypt.h +++ b/storage/innobase/include/fil0crypt.h @@ -75,6 +75,21 @@ struct key_struct (that is L in CRYPT_SCHEME_1) */ }; +/** is encryption enabled */ +extern ulong srv_encrypt_tables; + +#ifdef UNIV_PFS_MUTEX +extern mysql_pfs_key_t fil_crypt_data_mutex_key; +#endif + +/** Mutex helper for crypt_data->scheme +@param[in, out] schme encryption scheme +@param[in] exit should we exit or enter mutex ? */ +void +crypt_data_scheme_locker( + st_encryption_scheme* scheme, + int exit); + struct fil_space_rotate_state_t { time_t start_time; /*!< time when rotation started */ @@ -96,13 +111,110 @@ struct fil_space_rotate_state_t struct fil_space_crypt_struct : st_encryption_scheme { + public: + /** Constructor. Does not initialize the members! + The object is expected to be placed in a buffer that + has been zero-initialized. */ + fil_space_crypt_struct( + ulint new_type, + uint new_min_key_version, + uint new_key_id, + ulint offset, + fil_encryption_t new_encryption) + : st_encryption_scheme(), + min_key_version(new_min_key_version), + page0_offset(offset), + encryption(new_encryption), + closing(false), + key_found(), + rotate_state() + { + key_found = new_min_key_version; + key_id = new_key_id; + my_random_bytes(iv, sizeof(iv)); + mutex_create(fil_crypt_data_mutex_key, + &mutex, SYNC_NO_ORDER_CHECK); + locker = crypt_data_scheme_locker; + type = new_type; + + if (new_encryption == FIL_SPACE_ENCRYPTION_OFF || + (!srv_encrypt_tables && + new_encryption == FIL_SPACE_ENCRYPTION_DEFAULT)) { + type = CRYPT_SCHEME_UNENCRYPTED; + } else { + type = CRYPT_SCHEME_1; + min_key_version = key_get_latest_version(); + } + } + + /** Destructor */ + ~fil_space_crypt_struct() + { + closing = true; + mutex_free(&mutex); + } + + /** Get latest key version from encryption plugin + @retval key_version or + @retval ENCRYPTION_KEY_VERSION_INVALID if used key_id + is not found from encryption plugin. */ + uint key_get_latest_version(void); + + /** Returns true if key was found from encryption plugin + and false if not. */ + bool is_key_found() const { + return key_found != ENCRYPTION_KEY_VERSION_INVALID; + } + + /** Returns true if tablespace should be encrypted */ + bool should_encrypt() const { + return ((encryption == FIL_SPACE_ENCRYPTION_ON) || + (srv_encrypt_tables && + encryption == FIL_SPACE_ENCRYPTION_DEFAULT)); + } + + /** Return true if tablespace is encrypted. */ + bool is_encrypted() const { + return (encryption != FIL_SPACE_ENCRYPTION_OFF); + } + + /** Return true if default tablespace encryption is used, */ + bool is_default_encryption() const { + return (encryption == FIL_SPACE_ENCRYPTION_DEFAULT); + } + + /** Return true if tablespace is not encrypted. */ + bool not_encrypted() const { + return (encryption == FIL_SPACE_ENCRYPTION_OFF); + } + + /** Is this tablespace closing. */ + bool is_closing(bool is_fixed) { + bool closed; + if (!is_fixed) { + mutex_enter(&mutex); + } + closed = closing; + if (!is_fixed) { + mutex_exit(&mutex); + } + return closed; + } + uint min_key_version; // min key version for this space ulint page0_offset; // byte offset on page 0 for crypt data fil_encryption_t encryption; // Encryption setup ib_mutex_t mutex; // mutex protecting following variables bool closing; // is tablespace being closed - bool inited; + + /** Return code from encryption_key_get_latest_version. + If ENCRYPTION_KEY_VERSION_INVALID encryption plugin + could not find the key and there is no need to call + get_latest_key_version again as keys are read only + at startup. */ + uint key_found; + fil_space_rotate_state_t rotate_state; }; -- cgit v1.2.1