动态

详情 返回 返回

MySQL 無法修改主鍵?原來是因為這個參數 - 动态 详情

同事諮詢了一個問題,TDSQL(for MySQL)中的某張表主鍵需要改為聯合主鍵,是否必須先刪除現有的主鍵?因為刪除主鍵時,提示這個錯誤。

作者:劉晨,網名 bisal ,具有十年以上的應用運維工作經驗,目前主要從事數據庫應用研發能力提升和技術管理相關的工作,Oracle ACE(Alumni),騰訊雲TVP,擁有 Oracle OCM & OCP 、EXIN DevOps Master 、SCJP 等國際認證,國內首批 Oracle YEP 成員,OCMU 成員,《DevOps 最佳實踐》中文譯者之一,CSDN & ITPub 專家博主,公眾號”bisal的個人雜貨鋪”,長期堅持分享技術文章,多次在線上和線下分享技術主題。

愛可生開源社區出品,原創內容未經授權不得隨意使用,轉載請聯繫小編並註明來源。

本文約 800 字,預計閲讀需要 2 分鐘。

問題背景

同事諮詢了一個問題,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)

解決方案

方案一

既然 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 | OFF   |
+-------------------------+-------+
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 | ON    |
+-------------------------+-------+
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

但可能的風險,就是刪除主鍵,再創建主鍵的這段時間內,如果有主鍵字段的重複數據插入,就可能導致創建新的主鍵不成功。另外,鑑於該參數設置成為非默認值,創建完主鍵,需要記得改過來。

方案二

如果 sql_require_primary_key 設置為 ON,意思就是表任何的時刻都需要有主鍵,不能出現真空。變更主鍵的操作,實際包含了刪除原主鍵和創建新的主鍵兩個步驟,因此只需要將兩個步驟合併成一個即可。

MySQL 支持多個語句一次執行,因此只需要將 alter table ... drop primary keyadd 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 的參數控制粒度很細,但通過各種應對方法,可以針對性解決特定的場景問題,但前提還是對參數的意義,以及場景的需求能充分了解,才能找到合適的解決方案。

user avatar ljc1212 头像 u_15745565 头像 developer-tianyiyun 头像 zeran 头像
点赞 4 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.