MySQL表添加了一個欄位,竟然導致數據無法寫入,反思

2021-02-19 楊建榮的學習筆記

這是學習筆記的第 2152 篇文章

  今天有一個同事通過即時通訊工具找我,說需要做一個數據變更操作,我一看需求很簡單,是新增了一個列,需要創建相關的索引。

  對於SQL自動化上線,目前算是到了收穫的時段,從近期的工單情況來看,很多業務需求都從平臺化的工單操作轉向了自動化單據,按照最新的數據統計結果,假設有150個工單,那麼100個左右都是自動化流程完成的,佔比近70%。

 這個工單的操作是目前自動化不支持的,因為需求是刪除已有的索引,然後添加新的索引欄位。

 當我看到問題的時候,我感覺到一種異常,但是又實在說不清楚,所以準備當面溝通下。

 

表結構信息如下:

CREATE TABLE `data_stat` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  `day` int(8) NOT NULL DEFAULT '0',

  `kind` varchar(10) NOT NULL DEFAULT '',

  `netid` varchar(3) NOT NULL DEFAULT '',

  `item` varchar(10) NOT NULL DEFAULT '' ,

  `value` varchar(20) NOT NULL DEFAULT '',

  `room` varchar(10) NOT NULL DEFAULT 'null' ,

  PRIMARY KEY (`id`),

  KEY `idx_day_netid` (`day`,`kind`,`netid`,`item`)

) ENGINE=InnoDB AUTO_INCREMENT=55158 DEFAULT CHARSET=utf8 ;

大體的業務含義是對每一天的登錄數據進行統計,原本是3個維度(kind,netid,item),現在多了一個維度(room)。

舉個小例子,數據可以這樣描述:

在2019-01-01(day)這一天用戶通過手機(kind)登錄了網站,使用的是5G手機(netid),連接的就近站點(room)是北京,在線時長(item)為5分鐘(value)。

此時我需要了解的是業務的查詢模型,即通常都有哪些場景的查詢,而一旦這個room新欄位在複合索引中,而如果條件不滿足,則這個索引列不會被用到,其實效果更糟。 

而通過溝通,我驚奇的發現業務對於這個表的使用是有問題的。他說如果不添加索引欄位room,業務就寫入不了數據了。 

這個大大超出了我的預期,大家可以仔細看下這條SQL,按照我剛剛描述的場景,是否能夠理解。

經過溝通,理解了這個業務場景,總算是明白了為什麼業務寫入不了數據。

可以使用如下的兩條數據描述來說明:

第1條記錄:

2019-01-01(day)用戶通過手機(kind)登錄了網站,使用的是5G手機(netid),連接的就近站點(room)是北京,在線時長(item)為5分鐘(value)

第2條記錄:

2019-01-01(day)用戶通過手機(kind)登錄了網站,使用的是5G手機(netid),連接的就近站點(room)是北京,在線時長(item)為15分鐘(value)

在這種情況下,因為欄位(day,kind,netid,item)是唯一性索引,那麼第2條記錄對應的數據是無法寫入的。 

所以按照這種設計,如果後續還有新的欄位,那索引就需要橫向擴展了,所以對於這個問題,我提出了改進建議。 

索引確實需要重建,根據業務反饋的查詢場景,其實添加非唯一性索引(`day`,`netid`,`room`)已經足夠覆蓋目前的查詢,而更有意義的是:數據寫入不會因為索引設計不合理/新增業務欄位而導致數據無法寫入。 

所以在明確了需求之後,幫業務同學重建了索引,這個問題的處理就告一段落。 

這個問題帶給我的總結就是:

對於潛在的問題,第一要旨就是參考標準,如果違反了標準,我們可以很快發現潛在問題,而不是屈從於被動響應業務。 

對於溝通,我們儘可能避免一些聊天式溝通,越是不夠明確清晰,我們的溝通成本反而更高,所以對於一些模糊問題,幾句話解釋不清楚的,我都喜歡當面溝通。 

理解業務需求的深層次含義。這個業務開始的反饋是很緊急,通過熟悉業務後的改進來看,其實和開始的描述是有偏差的,業務緊急的深層次含義其實是業務因為新增欄位導致寫入不了數據了,所以迫切需要重建索引。而我們理解這個問題的出發點是基於數據統計查詢。而幫助業務解決了這個問題之後,對他們來說,收益更大,所以在溝通中也就淡化了這種緊急度。 

需要換位思考,從熟悉業務的角度來進行優化調整。在這個過程中,我是本著幫他的態度去理解這個問題的,在溝通中不斷的調整自己的問題分析方向,最終發現這個問題,解決這個問題的過程其實是無法預料到這麼多潛在的問題的,而逐步理解了業務,也就掌握了主動性。

索引優化的知識補充,通過這個問題,無論是歷史遺留還是新人犯的錯誤,其實都從側面反映出我們需要提供一些可供參考的技術建議,這是一個持續改進的過程。

近期熱文:

遷移到MySQL的業務架構演進實戰

資料庫修改密碼風險高,如何保證業務持續,這幾種密碼雙活方案可以參考

MySQL業務雙活的初步設計方案

如何優化MySQL千萬級大表,我寫了6000字的解讀

一道經典的MySQL面試題,答案出現三次反轉

業務雙活的數據切換思路設計(下)

業務雙活的數據切換思路設計(一)

MySQL中的主鍵和rowid,看似簡單,其實有一些使用陷阱需要注意

小白學MySQL要多久?我整理了10多個問題的答案

轉載熱文:

《吊打面試官》系列-Redis基礎

唯一ID生成算法剖析,看看這篇就夠了

關於大數據運維能力的一些思考

DBA菜鳥的進化簡史:不忘初心,記工作中踩過的三個坑

美女主持直播,被突發意外打斷!灣區網友卻高喊: 我懂!超甜

QQ群號:763628645

QQ群二維碼如下, 添加請註明:姓名+地區+職位,否則不予通過

相關焦點

  • MySQL中如何針對表進行添加、修改、刪除欄位?
    昨兒和大家一起看了,如何創建表,及建表過程中的注意事項,今天我們繼續針對表的操作來分享,主要是關於如何針對表進行,添加、修改和刪除欄位等內容,具體我們來一起看下。前期的準備工作,還是一樣的,進入mysql,進入我們自己創建的資料庫mysql_test,找到需要修改的表,先來看一下目前表的結構:desc emp;
  • mysql怎麼處理大表在不停機的情況下增加欄位
    直接添加欄位使用場景: 在系統不繁忙或者該表訪問不多的情況下,如符合ONLINE DDL的情況下,可以直接添加。模擬場景: 創建一個測試腳本,每10s訪問該表隨機一條記錄,然後給該表添加欄位訪問腳本如下:#!
  • MySQL資料庫教程-數據表欄位約束
    記錄是存儲結構化數據的基本單元。在實際進行欄位設置及值存儲過程中,需要結合實際情況確定每一個欄位存儲數據的格式,規範與要求。這些規範格式等即為欄位的約束。如學生的聯繫電話不允許出現重複,就需要定義與之對應的欄位約束。
  • MySQL和Oracle的添加欄位的處理差別 (r10筆記第73天)
    昨天在微信群中有個朋友也是無意中問了一下,說資料庫中的表欄位想保持一種相對規範的順序,怎麼辦?沒法在已有的欄位1,欄位2中間添加一個欄位3。但是MySQL卻可以,這個方面MySQL看起來要靈活的多,這個是什麼原因呢,他們在設計上有什麼差別呢。MySQL中對每個表存在一個定義文件,即frm文件,我們來取出一個表,看看能不能簡單解析一下。
  • 【問答】MySQL如何給欄位添加注釋
    s_no 和 s_name 後面通過關鍵字 comment 來給對應的欄位添加注釋。comment 關鍵字後面用單引號括起來的就是你需要給這個欄位添加的注釋。② 當你已經創建好表了,但是發現忘記注釋或者注釋的內容需要改變的時候,你可以通過以下命令去更改 student  表的 s_name  欄位的注釋alter table student modify s_name varchar(100) comment '姓名-更改';‍show full
  • 原創MySql專題之第三篇--表的操作
    表格行被稱為記錄(表中的數據),表格列被稱為欄位。的特色,其他資料庫中無法使用二、添加、修改和刪除表中的數據【insert,update,delete(DML語句)】insert:省略之後程序不建壯,無法修改表結構,可能導致insert語句執行失敗中文亂碼:在dos
  • 【社區精選43】Excel導入MySQL數據出現欄位錯行原因&解決方案
    當導入fct_sales_item的時候發現,數據存在一個錯列有問題。也就是對比MySQL資料庫原表的列的順序,會發現該表的表頭與資料庫中原表的欄位列不一樣。當導入數據時候,excel會對原表頭進行重新排序。本案例中:導入的數據表頭是按欄位名稱的英文字母的升序順序。而不是按原來數據表中的欄位順序。這會導致當導入的數據出現格式錯誤無法導入。
  • 愛可生詳解MySQL|刪庫了數據無法恢復?教你讓資料庫起死回生
    備份恢復後無法啟動服務什麼情況?表定義損壞數據無法讀取怎麼辦?我曾遇到某初創網際網路企業,因維護人員不規範的備份恢復操作,導致系統表空間文件被初始化,上萬張表無法讀取,花了數小時才搶救回來。當你發現數據無法讀取時,也許並非數據丟失了,可能是 DBMS 找不到描述數據的信息。
  • MySQL mysqldump 數據導出詳解
    ,而mysqldump是導出數據過程中使用非常頻繁的一個工具;它自帶的功能參數非常多,文章中會列舉出一些常用的操作,在文章末尾會將所有的參數詳細說明列出來。>注意導出指定表只能針對一個資料庫進行導出,且導出的內容中和導出資料庫也不一樣,導出指定表的導出文本中沒有創建資料庫的判斷語句,只有刪除表-創建表-導入數據mysqldump -uroot -proot --databases db1 --tables a1 a2  >/tmp/db1.sql
  • 基礎SQL-DML語句-對資料庫表數據增刪改
    新增記錄1.1 新增全部欄位數據羅列所有的欄位INSERT INTO 表名 (欄位名1, 欄位名2, 欄位名3…)  VALUES (值1, 值2, 值3);不寫欄位名INSERT INTO 表名 VALUES (值1, 值2, 值3…);此時值的個數,順序,類型要和資料庫表欄位的個數,順序,類型保持一致1.2 新增部分欄位數據
  • EXCEL操作資料庫表,自動判斷欄位類型,批量添加數據到資料庫表
    使用SQL語句添加數據時,不同的欄位類型要求不一樣,字符類型要求要用單引號括起來,數字類型則什麼都不用加,時間日期類型要前面後井號"#",如果不按要求寫語句將會出錯。所在在添加數據時要把每個欄位類型都弄清楚,很容易出錯,所以研究了一下自動檢測欄位類型,然後根據不同的類型為每個欄位使用不同的寫法。
  • 面試官:MySQL表設計要注意什麼?
    所以啦,反正都要生成一個主鍵,那你還不如自己指定一個主鍵,在有些情況下,就能顯式的用上主鍵索引,提高查詢效率!問題2:主鍵是用自增還是UUID?回答:肯定答自增啊。innodb 中的主鍵是聚簇索引。如果主鍵是自增的,那麼每次插入新的記錄,記錄就會順序添加到當前索引節點的後續位置,當一頁寫滿,就會自動開闢一個新的頁。
  • 第09期:有關 MySQL 字符集的亂碼問題
    那麼數據亂碼問題在這兒顯得就非常簡單了,或許說可能不會出現這樣的問題。數據之所以會亂碼,在 MySQL 裡無非有以下幾類情況:在數據寫入到表的過程中轉碼失敗,資料庫端也沒有進行恰當的處理,導致存放在表裡的數據亂碼。針對這種情況,前幾篇文章介紹過客戶端發送請求到服務端。其中任意一個編碼不一致,都會導致表裡的數據存入不正確的編碼而產生亂碼。
  • Excel|數據透視表添加計算欄位替代繁瑣的函數計算
    完成這項工作最方便的方法就是利用數據透視表的增加」計算欄位「功能。公式實現第一步:添加數據透視表滑鼠放在工作表數據區域任意單元格位置,選擇」插入「菜單中的」數據透視表「,這增加直觀的對比效果,我選擇放置位置為本工作表的F1單元格,如下圖:將」部門「與」姓名
  • MySQL導出數據為csv的方法
    將資料庫中的數據導出成csv格式的文件CSV格式,其要點包括:(1)欄位之間以逗號分隔,數據行之間以\r\n分隔;
  • Hive表欄位Comment中文亂碼
    1.問題描述默認Hive中創建有中文注釋的表時,無論是在Hive CLI還是Hue中該注釋顯示都會是亂碼。2.解決辦法這個問題是因為mysql中的元資料庫表COLUMNS_V2中的欄位COMMENT編碼問題導致的,需要設置為utf-8,如下所示:
  • MYSQL面試常考知識點總結
    分庫     分表能夠解決單表數據量過大帶來的查詢效率下降的問題,但是,卻無法給資料庫的並發處理能力帶來質的提升。面對高並發的讀寫訪問,對資料庫進行拆分,從而提高資料庫寫入能力,這就是所謂的分庫!
  • SQL學習筆記(四)----表數據操作的SQL語句
    ★主要學習表數據的操作:查詢、添加、修改、刪除數據」表數據操作的SQL語句1. 查詢數據---1.全列插入:值的順序與表結構欄位的順序完全一一對應insert into 表名 values(...)例:舉一個列子:insert into students values(0,'xx',default,default,'男');insert into students values
  • mysql大表中count()的用法以及mysql中count()的優化
    本篇文章給大家帶來的內容是關於mysql大表中count()的用法以及mysql中count()的優化,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。一個單表中包含有6000w+的數據,然而你又不能拆分.需要分別統計表中有多少數據,A產品有多少,B產品有多少這幾個數據.
  • Java開發工程師如何在Mysql資料庫中創建表
    首先我們需要在資料庫中創建兩張表用來學習MyBatis對資料庫增刪改查的使用方法。如果是新安裝的資料庫可以直接複製我下面的sql進行表創建,如果是已使用中的資料庫可能表明會與我的表名衝突,需要創建一個新的database再執行sql,也可以直接刪除原來的表,如果表有外鍵關聯需要先解除外鍵約束再刪除。