Index: src/wp-includes/meta.php
===================================================================
--- src/wp-includes/meta.php	(revision 32594)
+++ src/wp-includes/meta.php	(working copy)
@@ -576,6 +576,31 @@
 		return false;
 	}
 
+	/**
+	 * Filter whether to retrieve metadata of a specific type by its meta ID.
+	 *
+	 * The dynamic portion of the hook, `$meta_type`, refers to the meta
+	 * object type (comment, post, or user). Returning a non-null value
+	 * will effectively short-circuit the retrieval.
+	 *
+	 * @since x.y.z
+	 *
+	 * @param null|object $value Whether to retrieve the meta row object.
+	 * @param int mixed $meta_id Meta row ID.
+	 */
+	$check = apply_filters( "get_{$meta_type}_meta_by_mid", null, $meta_id );
+	if ( null !== $check ) {
+		if ( empty( $check ) ) {
+			return false;
+		}
+
+		if ( isset( $check->meta_value ) ) {
+			$check->meta_value = maybe_unserialize( $check->meta_value );
+		}
+
+		return $check;
+	}
+
 	$id_column = ( 'user' == $meta_type ) ? 'umeta_id' : 'meta_id';
 
 	$meta = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table WHERE $id_column = %d", $meta_id ) );
@@ -621,6 +646,25 @@
 	$column = sanitize_key($meta_type . '_id');
 	$id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id';
 
+	/**
+	 * Filter whether to update metadata of a specific type by its meta ID.
+	 *
+	 * The dynamic portion of the hook, `$meta_type`, refers to the meta
+	 * object type (comment, post, or user). Returning a non-null value
+	 * will effectively short-circuit the update.
+	 *
+	 * @since x.y.z
+	 *
+	 * @param null|bool $check Whether to allow updating metadata for the given type.
+	 * @param int $meta_id Meta row ID.
+	 * @param mixed $meta_value Meta value. Must be serializable if non-scalar.
+	 * @param string|bool $meta_key Meta key to update.
+	 */
+	$check = apply_filters( "update_{$meta_type}_meta_by_mid", null, $meta_id, $meta_value, $meta_key );
+	if ( null !== $check ) {
+		return false;
+	}
+
 	// Fetch the meta and go on if it's found.
 	if ( $meta = get_metadata_by_mid( $meta_type, $meta_id ) ) {
 		$original_key = $meta->meta_key;
@@ -711,6 +755,23 @@
 	$column = sanitize_key($meta_type . '_id');
 	$id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id';
 
+	/**
+	 * Filter whether to delete metadata of a specific type by its meta ID.
+	 *
+	 * The dynamic portion of the hook, `$meta_type`, refers to the meta
+	 * object type (comment, post, or user). Returning a non-null value
+	 * will effectively short-circuit the deletion.
+	 *
+	 * @since x.y.z
+	 *
+	 * @param null|bool $check Whether to allow deleting metadata for the given type.
+	 * @param int $meta_id Meta row ID.
+	 */
+	$check = apply_filters( "delete_{$meta_type}_meta_by_mid", null, $meta_id );
+	if ( null !== $check ) {
+		return false;
+	}
+
 	// Fetch the meta and go on if it's found.
 	if ( $meta = get_metadata_by_mid( $meta_type, $meta_id ) ) {
 		$object_id = $meta->{$column};
Index: tests/phpunit/tests/meta.php
===================================================================
--- tests/phpunit/tests/meta.php	(revision 32594)
+++ tests/phpunit/tests/meta.php	(working copy)
@@ -31,6 +31,11 @@
 		$this->assertFalse( delete_metadata_by_mid( 'user', 0 ) );
 		$this->assertFalse( delete_metadata_by_mid( 'non_existing_meta', $this->delete_meta_id ) );
 
+		// Test short-circuiting deletion.
+		add_filter( 'delete_user_meta_by_mid', '__return_true' );
+		$this->assertFalse( delete_metadata_by_mid( 'user', $this->delete_meta_id ) );
+		remove_filter( 'delete_user_meta_by_mid', '__return_true' );
+
 		// Now let's delete the real meta data
 		$this->assertTrue( delete_metadata_by_mid( 'user', $this->delete_meta_id ) );
 
@@ -76,6 +81,11 @@
 		$this->assertTrue( update_metadata_by_mid( 'user', $this->meta_id, 'other_meta_value' ) );
 		$second = get_user_meta( $meta->user_id, $meta->meta_key );
 		$this->assertFalse( $first === $second );
+
+		// Test short-circuiting updates.
+		add_filter( 'update_user_meta_by_mid', '__return_true' );
+		$this->assertFalse( update_metadata_by_mid( 'user', $this->meta_id, 'meta_new_value' ) );
+		remove_filter( 'update_user_meta_by_mid', '__return_true' );
 	}
 
 	/**
