暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

"sql_require_primary_key"参数为ON如何修改主键?

315

同事咨询了一个问题,TDSQL(for MySQL)中的某张表主键需要改为联合主键,是否必须先删除现有的主键?因为删除主键时,提示这个错误,

    [test]> alter table test drop primary key;
    ERROR 3750 (HY000): Unable to create or change a table without a primary key, 
    when the system variable 'sql_require_primary_key' is set. 
    Add a primary key to the table or unset this variable to avoid this message. 
    Note that tables without a primary key can cause performance problems in row-based replication, 
    so please consult your DBA before changing this setting.

    从提示上可以看到具体的原因,当设置了"sql_require_primary_key"参数,不能创建或改变一张没有主键的表。解决方案是增加主键或者删除此参数避免错误,同时提醒了,如果表无主键,可能会导致基于行的复制产生性能问题。

    "sql_require_primary_key"参数控制的是强制检查主键,可以动态修改,

      参数名称:sql_require_primary_key
      作用范围:Global & Session
      动态修改:Yes
      默认值:OFF
      该参数设置为ON时,SQL语句create table创建新表或者alter语句对已存在的表进行修改,将会强制检查表中是否包含主键,如果没有主键,则会报错。

      针对这个场景,是否还可以将主键改为联合主键?

      创建一张测试表,主键初始是id,

        bisal@mysqldb:  [test]> create table t_primary_key (id int, c1 varchar(1), c2 varchar(1), constraint pk_t_id primary key(id));
        Query OK, 0 rows affected (0.07 sec)

        解决方案1

        既然"sql_require_primary_key"参数控制了强制检验主键,而且又是可动态修改的,临时关闭,再打开即可,

          bisal@mysqldb:  [test]> alter table t_primary_key drop primary key;
          ERROR 3750 (HY000): Unable to create or change a table without a primary key, when the system variable 'sql_require_primary_key' is set. Add a primary key to the table or unset this variable to avo


          bisal@mysqldb: [(none)]> show variables like '%sql_require%';
          +-------------------------+-------+
          | Variable_name | Value |
          +-------------------------+-------+
          | sql_require_primary_key | ON    |
          +-------------------------+-------+
          1 row in set (0.00 sec)


          bisal@mysqldb: [(none)]> set sql_require_primary_key = ON;
          Query OK, 0 rows affected (0.02 sec)


          bisal@mysqldb: [(none)]> show variables like '%sql_require%';
          +-------------------------+-------+
          | Variable_name | Value |
          +-------------------------+-------+
          | sql_require_primary_key | OFF   |
          +-------------------------+-------+
          1 row in set (0.00 sec)


          bisal@mysqldb:  [test]> alter table t_primary_key drop primary key;
          Query OK, 0 rows affected (0.10 sec)
          Records: 0 Duplicates: 0 Warnings: 0

          但可能的风险,就是删除主键,再创建主键的这段时间内,如果有主键字段的重复数据插入,就可能导致创建新的主键不成功。另外,鉴于该参数设置成为非默认值,创建完主键,需要记得改过来。

          解决方案2

          如果"sql_require_primary_key"设置为ON,意思就是表任何的时刻都需要有主键,不能出现真空。变更主键的操作,实际包含了删除原主键和创建新的主键两个步骤,因此只需要将两个步骤合并成一个即可。

          MySQL支持多个语句一次执行,因此只需要将alter table ... drop primary key和add constraint ... primary key ...合成一条语句,

            bisal@mysqldb:  [test]> alter table t_primary_key drop primary key, add constraint pk_t_01 primary key (id, c1);
            Query OK, 0 rows affected (0.06 sec)
            Records: 0  Duplicates: 0  Warnings: 0

            从这个问题可以看出来,MySQL的参数控制粒度很细,但通过各种workaround,可以针对性解决特定的场景问题,前提还是对参数的意义,以及场景的需求能充分了解,才能找到合适的解决方案。


            如果您认为这篇文章有些帮助,还请不吝点下文章末尾的"点赞"和"在看",或者直接转发pyq,




            近期更新的文章:
            公众号1400篇文章分类和索引
            公众号1400篇文章数据统计
            中国足球现状
            SQL统计腾讯会议参会信息技巧
            AirTag无GPS怎么定位?

            近期的热文:
            推荐一篇Oracle RAC Cache Fusion的经典论文
            "红警"游戏开源代码带给我们的震撼

            文章分类和索引:
            公众号1400篇文章分类和索引

            文章转载自bisal的个人杂货铺,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

            评论