WL#11807: Add sysvar which prohibits pk-less tables

Affects: Server-8.0   —   Status: Complete   —   Priority: Medium

Tables without PK can cause performance problems on the slave when doing
row-based replication. The resulting inconsistencies will generate replication
breakage on any slaves which will exacerbate the problem and require additional

Add a system variable sql_require_primary_key (global & session), which if set,
causes CREATE or ALTER statements that would yield a table without PK, to fail


"A recent incident came up due to a largish table being created without a
primary key on a RBR based master server. (MySQL 5.5 but 5.6 behaves the same).

Later a query was sent to the server which CHANGE a significant part of the
table.  In our case this was a DELETE of several rows, an UPDATE would have had
the same result.  On the master this did the equivalent of a _single table scan_
and did not take too long so went unnoticed.

However, given the server was using RBR, this was replicated for each changed
row as the function equivalent for each row that was changed:

    UPDATE some_table SET col3=X WHERE col1=A AND col2=B AND col4=C AND ...
coln = Z

On the slaves this then triggered the equivalent of N table scans where in our
case N was a large number and thus generated a severe replication delay.

While this behaviour is documented and known, it is easy to dig yourself into a
hole, and recovering from this requires waiting for changes to propagate through
(the delay was too large in our case) or doing other manual work on each slave
to resolve the issue." 

From BUG#69845.
F1: Have system variable sql_require_primary_key
F2: RPK must be settable @ session level
F3: RPK must be settable @ global level -> new default for new connections
F4: Default is OFF
F5: When RPK is set, create of table without explicit PK must fail
F6: When RPK is set, dropping the PK column from a table must fail
F7: When RPK is set, create like <PK-less table> must fail
F8: When RPK is set, create ... as must fail unless a PK-signature is used (even
select * from <table w/ PK>
F9: When RPK is set, import of a PK-less table must fail
F10: RPK must be settable on the command line without interfering with the
creation of PK-less system tables during initialize/bootstrap.
F11: RPK must not prevent the PK from being dropped and a added by a single
ALTER statemnt
F12: RPK must also prevent PK-less temporary tables.
F13: RPK setting must be propagated to the slave applier
F14: RPK can only be set with SUPER or SYSTEM_VARIABLES_ADMIN privilege.
- Add new system variable to existing variables in sql/sys_vars.cc

Using the correct arguments when creating the global object representing the
system variable will ensure that requirements F1-F4 is satisfied.

- Specify check_has_super as the check function argument to ensure that
privileges are checked. This will satisfy requirement F14.

- Check the value of the variable in  mysql_prepare_create_table() and return
error if true and table does not have PK.

This function is already called for both CREATE and ALTER, and already sets a
variable to indicate if the created or altered table has a primary key.
Consequently, a check of this variable will satisfy requiremens F5-F8 and
F11-F12. By also testing for thd->is_dd_system_thread() and
thd->is_initialize_system_thread() F10 is satisfied.

- Check the value of the variable in Import_target::load and return error if
true and the deserialized dd::Table object does not have PK. This check will
satisfy requirement F9.

- Add another binlog event to propagate the current setting of the sysvar to the
slave applier. This is needed to satisfy requirement F13.