成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

MySQL JSON 類型 NOT NULL 竟無(wú)法約束 NULL 值插入?

數(shù)據(jù)庫(kù) MySQL
正向解析 binlog 生成 SQL 看并無(wú)問(wèn)題,binlog 里記錄的確實(shí)是 '' (空)值。但是通過(guò)查看線上表數(shù)據(jù)發(fā)現(xiàn),在 有 JSON NOT NULL? 類型的約束下,對(duì)應(yīng)的回滾 SQL 主鍵值竟然是 NULL 值! 這和 binlog 里記錄的 '' (空)值不一致。

故障現(xiàn)象

業(yè)務(wù)人員執(zhí)行了 DELETE 操作,導(dǎo)致數(shù)據(jù)誤刪除,需要數(shù)據(jù)回滾。通過(guò)工具回滾時(shí),發(fā)現(xiàn)回滾生成的 SQL 執(zhí)行時(shí)報(bào)錯(cuò):

ERROR 3140 (22032) at line 38454 in file: 'rollback.9591.sql': Invalid JSON text: "The document is empty." at position 0 in value for column 'life_band_dig_query.search_stats'.

起初,以為是 SQL 里的反斜杠導(dǎo)致數(shù)據(jù)被截?cái)嗔耍瑂ed 完再導(dǎo)入 SQL 發(fā)現(xiàn)還是有問(wèn)題。SQL 文件不小,表也很寬,很難檢查問(wèn)題,但還是試著分析數(shù)據(jù),發(fā)現(xiàn)反斜杠是對(duì)的。汗。。。

又通過(guò)報(bào)錯(cuò)仔細(xì)分析對(duì)應(yīng)字段 search_stats 的值,發(fā)現(xiàn) JSON 字段類型回滾生成的 SQL 竟然是 '' (空)值!

  • 版本:MySQL 5.7.21
  • SQL_MODE: ''

故障分析

正向解析 binlog 生成 SQL 看并無(wú)問(wèn)題,binlog 里記錄的確實(shí)是 '' (空)值。

但是通過(guò)查看線上表數(shù)據(jù)發(fā)現(xiàn),在 有 JSON NOT NULL 類型的約束下,對(duì)應(yīng)的回滾 SQL 主鍵值竟然是 NULL 值! 這和 binlog 里記錄的 '' (空)值不一致。

正常寫入 NULL 值,會(huì)觸發(fā)約束報(bào)錯(cuò),猜測(cè)可能是歷史上有過(guò) DDL 操作。

故障復(fù)現(xiàn)

將 SQL_MODE 設(shè)置為 '',退出重連。(PS:切記重連生效!)

MySQL [xuzong]> create table q(id int ,age varchar(200) default NULL);
Query OK, 0 rows affected (0.0107 sec)

MySQL [xuzong]> insert into q values(1,NULL);
Query OK, 1 row affected (0.0040 sec)

MySQL [xuzong]> select * from q;
+----+------+
| id | age  |
+----+------+
|  1 | NULL |
+----+------+
1 row in set (0.0020 sec)

MySQL [xuzong]> alter table q modify age json not null ;
Query OK, 1 row affected, 1 warning (0.0164 sec)

# 注意到這里有 Warning,感覺(jué)這種情況應(yīng)該是 Error 才對(duì)。
Records: 1  Duplicates: 0  Warnings: 1
Warning (code 1265): Data truncated for column 'age' at row 1

# 到這里就發(fā)現(xiàn)不對(duì)勁了,不僅有 null 值,而且還由 NULL 大寫變成了小寫。
MySQL [xuzong]> select * from q;
+----+------+
| id | age  |
+----+------+
|  1 | null |
+----+------+
1 row in set (0.0020 sec)

MySQL [xuzong]> show create table q \G
*************************** 1.row ***************************
       Table: q
Create Table: CREATE TABLE`q` (
`id` int(11) DEFAULT NULL,
`age` json NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
1rowinset (0.00 sec)

# 查一下試試,也能查出來(lái)
MySQL [xuzong]> select * from q  WHERE JSON_EXTRACT(age, '$.age') IS NULL;
+----+------+
| id | age  |
+----+------+
|  1 | null |
+----+------+
1 row in set (0.0019 sec)

# update 一下試試 binlog 是怎么記錄的
MySQL [xuzong]> update q set id=2 where id=1;
Query OK, 1 row affected (0.0023 sec)
Rows matched: 1  Changed: 1  Warnings: 0

# 用 5.7.21 的 mysqlbinlog 解析出來(lái) binlog:null 值 update 的時(shí)候 binlog 會(huì)記錄為 ''
### UPDATE `xuzong`.`q`
### WHERE
###   @1=1 /* INT meta=0 nullable=1 is_null=0 */
###   @2='' /* JSON meta=4 nullable=0 is_null=0 */
### SET
###   @1=2 /* INT meta=0 nullable=1 is_null=0 */
###   @2='' /* JSON meta=4 nullable=0 is_null=0 */

問(wèn)題處理

查到是字段兼容性問(wèn)題就好處理了,方法如下:

新建一個(gè)庫(kù),建議一個(gè)同表結(jié)構(gòu)的表,將 JSON 字段改寫為 TEXT 字段,然后將回滾 SQL 導(dǎo)入。再 UPDATE 修改 '' (空)值為 {},然后再修改為 JSON 字段。業(yè)務(wù)判斷數(shù)據(jù)是否正確,INSERT ... SELECT ... 寫入回原表。

這樣就解決了。。。

后續(xù)測(cè)試

其他版本 MySQL 是否存在同樣的問(wèn)題?親測(cè) 5.7.35 和 5.7.44 也同樣存在,這里不再概述。

但是用 MySQL 8.0 的 mysqlbinlog 去解析 binlog,記錄為 null。

測(cè)試 VARCHAT 類型

MySQL [xuzong]> create table j (id int , age varchar(20));
Query OK, 0 rows affected (0.01 sec)

MySQL [xuzong]> insert into j values (1,NULL);
Query OK, 1 row affected (0.01 sec)

MySQL [xuzong]> select * from j;
+------+------+
| id   | age  |
+------+------+
|    1 | NULL |
+------+------+
1 row in set (0.01 sec)

MySQL [xuzong]> alter table j modify age varchar(20) not null;
Query OK, 1 row affected, 1 warning (0.01 sec)
Records: 1  Duplicates: 0  Warnings: 1

MySQL [xuzong]>  show Warnings;
+---------+------+------------------------------------------+
| Level   | Code | Message                                  |
+---------+------+------------------------------------------+
| Warning | 1265 | Data truncated for column 'age' at row 1 |
+---------+------+------------------------------------------+
1 row in set (0.00 sec)

MySQL [xuzong]> select * from j;
+------+-----+
| id   | age |
+------+-----+
|    1 |     |
+------+-----+
1 row in set (0.00 sec)

這樣看的 VARCHAR 會(huì)自動(dòng)轉(zhuǎn)換為空值。

SQL_MODE

# 再執(zhí)行復(fù)現(xiàn)操作就報(bào)錯(cuò)了,所以還是建議線上開(kāi)啟嚴(yán)格模式的。
set global sql_mode=deafult;

用 ibd2sql 解析一下 ibd 文件,發(fā)現(xiàn)數(shù)據(jù)是正確的:

[root@nvm-22vdnhahrwnq37 ibd2sql-main]# python3 main.py ../mysql4223/xuzong/j.ibd --sql --ddl
CREATE TABLE IF NOT EXISTS `xuzong`.`j`(
    `id` int NULL,
    `age` json NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ;
INSERT INTO `xuzong`.`j` VALUES (2, '{}');

總結(jié)

  1. 線上修改表結(jié)構(gòu),一定要先備份數(shù)據(jù),然后在測(cè)試環(huán)境上修改表結(jié)構(gòu),測(cè)試通過(guò)后再上線。
  2. 修改表結(jié)構(gòu)時(shí),一定要注意數(shù)據(jù)類型的變化,特別是 JSON、BLOB 等特殊類型的變化。
  3. 建議線上開(kāi)啟 SQL_MODE 嚴(yán)格模式,避免出現(xiàn)一些意想不到的問(wèn)題。
  4. 本次問(wèn)題不影響線上數(shù)據(jù)以及主從復(fù)制,理論上來(lái)說(shuō)只是 MySQL 5.7 版本 mysqlbinlog 的問(wèn)題,以及違反了非空約束。

責(zé)任編輯:武曉燕 來(lái)源: 愛(ài)可生開(kāi)源社區(qū)
相關(guān)推薦

2022-05-08 18:18:40

JDKValueHashMap

2022-01-27 07:02:52

JavaHashMap單線程

2023-10-26 14:30:05

MySQLInnoDB

2010-05-31 15:23:02

MySQL數(shù)據(jù)庫(kù)NUL

2010-09-28 11:48:36

SQL NULL值

2023-05-10 16:15:58

javaScript算法開(kāi)發(fā)

2024-06-06 08:10:30

多線程Mapnull

2017-09-05 09:02:06

Oraclenot null優(yōu)化

2015-07-20 17:05:38

SQL ServerNULL值

2025-01-20 07:10:00

LambdaJavanull

2022-09-13 08:33:05

SQLNULL三值邏輯

2020-07-09 10:15:55

空值Bug語(yǔ)言

2018-02-06 08:32:09

MySQLNull程序員

2021-06-07 07:59:29

MySQL數(shù)據(jù)庫(kù) Get

2009-08-24 13:52:04

C# 泛型約束

2024-12-09 09:20:00

MySQLNULL 值

2010-09-17 10:24:47

SQL中IS NULL

2010-11-26 13:40:58

MySQL空字符串

2019-11-07 16:51:15

NULL三值邏輯SQL

2025-02-11 00:11:00

NULL運(yùn)算篩選
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 99伊人 | 中文日韩在线视频 | 天天操夜夜爽 | 亚洲高清视频在线 | 日韩一区在线观看视频 | 免费同性女女aaa免费网站 | 久久99精品久久久水蜜桃 | 久久久蜜臀国产一区二区 | 久久精品免费一区二区三 | 欧美成人一区二区三区 | 精品欧美一区二区三区久久久小说 | 五月天婷婷久久 | 国产精品亚洲综合 | 欧美日韩精品一区二区三区蜜桃 | 成人视屏在线观看 | 一区二区三区在线播放 | 狠狠操狠狠操 | 九九综合 | 国产日日操 | 国产在线永久免费 | 一区二区三区国产好 | 国产精品亚洲第一 | 亚洲人成在线观看 | 国产一区免费 | 亚洲一区精品视频 | 色伊人| 国产在线一区二区 | 欧美日韩精品一区二区 | 国产精品久久久亚洲 | 欧美一级在线观看 | 成人免费视频在线观看 | 精品中文在线 | 国产在线视频三区 | 日韩成人免费视频 | 国产福利在线 | 一区二区在线视频 | 亚洲成人播放器 | 亚洲一区二区三区在线 | 亚洲国产精品一区二区第一页 | 久草免费在线视频 | 亚洲美女一区二区三区 |