婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > MySQL數字類型自增的坑

MySQL數字類型自增的坑

熱門標簽:大豐地圖標注app 呂梁外呼系統 html地圖標注并導航 400電話辦理服務價格最實惠 南太平洋地圖標注 北京金倫外呼系統 400電話變更申請 武漢電銷機器人電話 催天下外呼系統

在進行表結構設計時,數字類型是最為常見的類型之一,但要用好數字類型并不如想象得那么簡單,比如:

  • 怎么設計一個互聯網海量并發業務的自增主鍵?用 INT 就夠了?
  • 怎么設計賬戶的余額?用 DECIMAL 類型就萬無一失了嗎?

以上全錯!

數字類型看似簡單,但在表結構架構設計中很容易出現上述“設計上思考不全面”的問題(特別是在海量并發的互聯網場景下)

數字類型

整數類型

MySQL 數據庫支持 SQL 標準支持的整型類型:INT、SMALLINT。此外,MySQL 數據庫也支持諸如 TINYINT、MEDIUMINT 和 BIGINT 整型類型(表 1 顯示了各種整型所占用的存儲空間及取值范圍):

MySQL數據類型 含義(有符號)
tinyint(m) 1個字節 范圍(-128~127)
smallint(m) 2個字節 范圍(-32768~32767)
mediumint(m) 3個字節 范圍(-8388608~8388607)
int(m) 4個字節 范圍(-2147483648~2147483647)
bigint(m) 8個字節 范圍(+-9.22*10的18次方)

在整型類型中,有 signed 和 unsigned 屬性,其表示的是整型的取值范圍,默認為 signed。在設計時,我不建議你刻意去用 unsigned 屬性,因為在做一些數據分析時,SQL 可能返回的結果并不是想要得到的結果。

來看一個“銷售表 sale”的例子,其表結構和數據如下。這里要特別注意,列 sale_count 用到的是 unsigned 屬性(即設計時希望列存儲的數值大于等于 0):

mysql> SHOW CREATE TABLE sale\G

*************************** 1. row ***************************

       Table: sale

Create Table: CREATE TABLE `sale` (

  `sale_date` date NOT NULL,

  `sale_count` int unsigned DEFAULT NULL,

  PRIMARY KEY (`sale_date`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci

1 row in set (0.00 sec)


mysql> SELECT * FROM sale;

+------------+------------+

| sale_date  | sale_count |

+------------+------------+

| 2020-01-01 |      10000 |

| 2020-02-01 |       8000 |

| 2020-03-01 |      12000 |

| 2020-04-01 |       9000 |

| 2020-05-01 |      10000 |

| 2020-06-01 |      18000 |

+------------+------------+

6 rows in set (0.00 sec)

其中,sale_date 表示銷售的日期,sale_count 表示每月的銷售數量。現在有一個需求,老板想要統計每個月銷售數量的變化,以此做商業決策。這條 SQL 語句需要應用到非等值連接,但也并不是太難寫:

SELECT 

    s1.sale_date, s2.sale_count - s1.sale_count AS diff

FROM

    sale s1

        LEFT JOIN

    sale s2 ON DATE_ADD(s2.sale_date, INTERVAL 1 MONTH) = s1.sale_date

ORDER BY sale_date;

然而,在執行的過程中,由于列 sale_count 用到了 unsigned 屬性,會拋出這樣的結果:

ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(`test`.`s2`.`sale_count` - `test`.`s1`.`sale_count`)'

可以看到,MySQL 提示用戶計算的結果超出了范圍。其實,這里 MySQL 要求 unsigned 數值相減之后依然為 unsigned,否則就會報錯。

為了避免這個錯誤,需要對數據庫參數 sql_mode 設置為 NO_UNSIGNED_SUBTRACTION,允許相減的結果為 signed,這樣才能得到最終想要的結果:

mysql> SET sql_mode='NO_UNSIGNED_SUBTRACTION';

Query OK, 0 rows affected (0.00 sec)

SELECT


    s1.sale_date,

    IFNULL(s2.sale_count - s1.sale_count,'') AS diff

FROM

    sale s1

    LEFT JOIN sale s2

    ON DATE_ADD(s2.sale_date, INTERVAL 1 MONTH) = s1.sale_date

ORDER BY sale_date;


+------------+-------+

| sale_date  | diff  |

+------------+-------+

| 2020-01-01 |       |

| 2020-02-01 | 2000  |

| 2020-03-01 | -4000 |

| 2020-04-01 | 3000  |

| 2020-05-01 | -1000 |

| 2020-06-01 | -8000 |

+------------+-------+

6 rows in set (0.00 sec)

浮點類型和高精度型

除了整型類型,數字類型常用的還有浮點和高精度類型。
MySQL 之前的版本中存在浮點類型 Float 和 Double,但這些類型因為不是高精度,也不是 SQL 標準的類型,所以在真實的生產環境中不推薦使用,否則在計算時,由于精度類型問題,會導致最終的計算結果出錯。
更重要的是,從 MySQL 8.0.17 版本開始,當創建表用到類型 Float 或 Double 時,會拋出下面的警告:MySQL 提醒用戶不該用上述浮點類型,甚至提醒將在之后版本中廢棄浮點類型

Specifying number of digits for floating point data types is deprecated and will be removed in a future release

而數字類型中的高精度 DECIMAL 類型可以使用,當聲明該類型列時,可以(并且通常必須要)指定精度和標度,例如:

salary DECIMAL(8,2)

其中,8 是精度(精度表示保存值的主要位數),2 是標度(標度表示小數點后面保存的位數)。通常在表結構設計中,類型 DECIMAL 可以用來表示用戶的工資、賬戶的余額等精確到小數點后 2 位的業務。

然而,在海量并發的互聯網業務中使用,金額字段的設計并不推薦使用 DECIMAL 類型,而更推薦使用 INT 整型類型(下文就會分析原因)。

業務表結構設計實戰

整型類型與自增設計

在真實業務場景中,整型類型最常見的就是在業務中用來表示某件物品的數量。例如上述表的銷售數量,或電商中的庫存數量、購買次數等。在業務中,整型類型的另一個常見且重要的使用用法是作為表的主鍵,即用來唯一標識一行數據。
整型結合屬性 auto_increment,可以實現自增功能,但在表結構設計時用自增做主鍵,希望你特別要注意以下兩點,若不注意,可能會對業務造成災難性的打擊:

  • 用 BIGINT 做主鍵,而不是 INT;
  • 自增值并不持久化,可能會有回溯現象(MySQL 8.0 版本前)。

從表 1 可以發現,INT 的范圍最大在 42 億的級別,在真實的互聯網業務場景的應用中,很容易達到最大值。例如一些流水表、日志表,每天 1000W 數據量,420 天后,INT 類型的上限即可達到。
因此,用自增整型做主鍵,一律使用 BIGINT,而不是 INT。不要為了節省 4 個字節使用 INT,當達到上限時,再進行表結構的變更,將是巨大的負擔與痛苦。
那這里又引申出一個有意思的問題:如果達到了 INT 類型的上限,數據庫的表現又將如何呢?是會重新變為 1?我們可以通過下面的 SQL 語句驗證一下:

mysql> CREATE TABLE t (

    ->     a INT AUTO_INCREMENT PRIMARY KEY

    -> );


mysql> INSERT INTO t VALUES (2147483647);

Query OK, 1 row affected (0.01 sec)


mysql> INSERT INTO t VALUES (NULL);

ERROR 1062 (23000): Duplicate entry '2147483647' for key 't.PRIMARY'

可以看到,當達到 INT 上限后,再次進行自增插入時,會報重復錯誤,MySQL 數據庫并不會自動將其重置為 1。
第二個特別要注意的問題是,MySQL 8.0 版本前,自增不持久化,自增值可能會存在回溯問題!

mysql> SELECT * FROM t;

+---+

| a |

+---+

| 1 |

| 2 |

| 3 |

+---+

3 rows in set (0.01 sec)


mysql> DELETE FROM t WHERE a = 3;

Query OK, 1 row affected (0.02 sec)


mysql> SHOW CREATE TABLE t\G

*************************** 1. row ***************************

       Table: t

Create Table: CREATE TABLE `t` (

  `a` int NOT NULL AUTO_INCREMENT,

  PRIMARY KEY (`a`)

) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci

1 row in set (0.00 sec

可以看到,在刪除自增為 3 的這條記錄后,下一個自增值依然為 4(AUTO_INCREMENT=4),這里并沒有錯誤,自增并不會進行回溯。但若這時數據庫發生重啟,那數據庫啟動后,表 t 的自增起始值將再次變為 3,即自增值發生回溯。具體如下所示:

mysql> SHOW CREATE TABLE t\G

*************************** 1. row ***************************

       Table: t

Create Table: CREATE TABLE `t` (

  `a` int NOT NULL AUTO_INCREMENT,

  PRIMARY KEY (`a`)

) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci

1 row in set (0.00 s

若要徹底解決這個問題,有以下 2 種方法:

  • 升級 MySQL 版本到 8.0 版本,每張表的自增值會持久化;
  • 若無法升級數據庫版本,則強烈不推薦在核心業務表中使用自增數據類型做主鍵。

其實,在海量互聯網架構設計過程中,為了之后更好的分布式架構擴展性,不建議使用整型類型做主鍵,更為推薦的是字符串類型。

資金字段設計

在用戶余額、基金賬戶余額、數字錢包、零錢等的業務設計中,由于字段都是資金字段,通常程序員習慣使用 DECIMAL 類型作為字段的選型,因為這樣可以精確到分,如:DECIMAL(8,2)。

CREATE TABLE User (

  userId BIGINT AUTO_INCREMENT,

  money DECIMAL(8,2) NOT NULL,

  ......

)

在海量互聯網業務的設計標準中,并不推薦用 DECIMAL 類型,而是更推薦將 DECIMAL 轉化為 整型類型。也就是說,資金類型更推薦使用用分單位存儲,而不是用元單位存儲。如1元在數據庫中用整型類型 100 存儲。

金額字段的取值范圍如果用 DECIMAL 表示的,如何定義長度呢?因為類型 DECIMAL 是個變長字段,若要定義金額字段,則定義為 DECIMAL(8,2) 是遠遠不夠的。這樣只能表示存儲最大值為 999999.99,百萬級的資金存儲。

用戶的金額至少要存儲百億的字段,而統計局的 GDP 金額字段則可能達到數十萬億級別。用類型 DECIMAL 定義,不好統一。
另外重要的是,類型 DECIMAL 是通過二進制實現的一種編碼方式,計算效率遠不如整型來的高效。因此,推薦使用 BIG INT 來存儲金額相關的字段。

字段存儲時采用分存儲,即便這樣 BIG INT 也能存儲千兆級別的金額。這里,1兆 = 1萬億。

這樣的好處是,所有金額相關字段都是定長字段,占用 8 個字節,存儲高效。另一點,直接通過整型計算,效率更高。
注意,在數據庫設計中,我們非常強調定長存儲,因為定長存儲的性能更好。

我們來看在數據庫中記錄的存儲方式,大致如下:

若發生更新,記錄 1 原先的空間無法容納更新后記錄 1 的存儲空間,因此,這時數據庫會將記錄 1 標記為刪除,尋找新的空間給記錄1使用,如:

上圖中*記錄 1 表示的就是原先記錄 1 占用的空間,而這個空間后續將變成碎片空間,無法繼續使用,除非人為地進行表空間的碎片整理。

那么,當使用 BIG INT 存儲金額字段的時候,如何表示小數點中的數據呢?其實,這部分完全可以交由前端進行處理并展示。作為數據庫本身,只要按分進行存儲即可。

到此這篇關于MySQL數字類型自增的坑的文章就介紹到這了,更多相關MySQL數字類型自增內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:
  • MySQL中日期型單行函數代碼詳解
  • Mysql 日期格式化及復雜日期區間查詢
  • MySQL 生成隨機數字、字符串、日期、驗證碼及 UUID的方法
  • MySQL關于字符串中數字排序的問題分析
  • MySQL實例精講單行函數以及字符數學日期流程控制

標簽:徐州 迪慶 無錫 自貢 西寧 麗水 南充 龍巖

巨人網絡通訊聲明:本文標題《MySQL數字類型自增的坑》,本文關鍵詞  MySQL,數字,類型,自增,的,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《MySQL數字類型自增的坑》相關的同類信息!
  • 本頁收集關于MySQL數字類型自增的坑的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    成人教育av在线| 国产精品亚洲第一区在线暖暖韩国| 一区二区三区四区av| 国产精品18久久久久久vr| 日韩欧美国产一区在线观看| 日韩国产精品91| 欧美久久久久免费| 免费在线成人网| 久久综合久久综合久久综合| 国产精品 欧美精品| 国产三级精品三级| 色综合天天狠狠| 亚洲福利视频一区二区| 欧美一级黄色大片| 国产成人精品影视| 夜夜亚洲天天久久| 在线播放中文一区| 国产专区欧美精品| 亚洲男帅同性gay1069| 欧美美女直播网站| 国产精品亚洲第一| 亚洲精品第1页| 欧美va日韩va| 色哟哟精品一区| 奇米精品一区二区三区在线观看 | 91精品国产欧美一区二区成人 | 婷婷开心久久网| 久久蜜桃av一区精品变态类天堂| 99久久综合精品| 喷白浆一区二区| 亚洲视频一区在线| www久久精品| 欧美肥妇毛茸茸| av电影在线观看一区| 琪琪一区二区三区| 亚洲在线一区二区三区| 国产亚洲制服色| 欧美伦理视频网站| 色婷婷综合久久久中文字幕| 国产一区二区三区| 日韩不卡免费视频| 一区二区三区在线影院| 中文av一区二区| 日韩精品中文字幕在线不卡尤物| 日本道精品一区二区三区| 日韩精品午夜视频| 一区二区三区资源| 国产欧美视频一区二区三区| 欧美福利视频导航| 在线免费观看日本欧美| 菠萝蜜视频在线观看一区| 狠狠色狠狠色合久久伊人| 日本亚洲最大的色成网站www| 国产精品盗摄一区二区三区| 精品日韩欧美在线| 日韩手机在线导航| 日韩小视频在线观看专区| 欧美日韩久久久久久| 欧美综合视频在线观看| 在线观看免费成人| 精品视频在线看| 欧美日韩成人综合天天影院| 欧美视频一区在线观看| 欧美三区在线视频| 69p69国产精品| 26uuu欧美| 欧美韩国一区二区| 亚洲视频网在线直播| 亚洲精品视频免费看| 亚洲精品国产品国语在线app| 亚洲黄一区二区三区| 亚洲国产人成综合网站| 午夜精品一区二区三区三上悠亚 | 亚洲精品视频一区二区| 日韩理论片一区二区| 136国产福利精品导航| 亚洲精品视频免费观看| 性做久久久久久免费观看欧美| 亚洲成av人片一区二区三区| 青椒成人免费视频| 成人性生交大片免费看在线播放| 成人小视频免费在线观看| 色哟哟日韩精品| 欧美mv和日韩mv国产网站| 国产精品日韩成人| 亚洲影院在线观看| 精一区二区三区| 色哟哟一区二区在线观看| 91成人在线免费观看| 亚洲午夜激情av| 欧美亚洲国产怡红院影院| 国产精品蜜臀av| 蜜桃久久av一区| 欧美三级中文字幕在线观看| 国产精品视频你懂的| 免费不卡在线观看| 欧美日韩国产在线播放网站| 精品国产免费一区二区三区四区 | 国产成人免费xxxxxxxx| 国产综合久久久久影院| 不卡高清视频专区| 欧美酷刑日本凌虐凌虐| 久久先锋影音av| 亚洲资源中文字幕| 国产精品一区二区91| 欧美日韩一区不卡| 国产拍欧美日韩视频二区| 午夜久久久久久久久久一区二区| 国产福利电影一区二区三区| 欧美偷拍一区二区| 国产精品欧美久久久久无广告| 日韩国产高清在线| 欧美亚洲免费在线一区| 欧美国产欧美综合| 激情综合亚洲精品| 日韩一级黄色片| 视频一区视频二区在线观看| 91丨九色丨蝌蚪丨老版| 国产色产综合色产在线视频| 美国三级日本三级久久99| 欧洲精品在线观看| 国产精品美女久久久久av爽李琼| 热久久久久久久| 欧美无乱码久久久免费午夜一区 | 国产精品一二三四五| 欧美日韩免费观看一区三区| 国产精品视频一二| 高清不卡一区二区| 2021中文字幕一区亚洲| 美国毛片一区二区三区| 91精品国产全国免费观看| 亚洲国产一区二区三区 | 国产99久久久国产精品免费看| 久久影院午夜片一区| 91影视在线播放| 国产精品18久久久久久久网站| 亚洲天天做日日做天天谢日日欢| 日韩美女视频在线| 在线播放91灌醉迷j高跟美女| 国产精华液一区二区三区| 亚洲国产精品久久久久婷婷884| 精品久久久久久久人人人人传媒| 成人综合婷婷国产精品久久| 日韩欧美在线网站| 奇米综合一区二区三区精品视频| 精品1区2区3区| 日日夜夜免费精品视频| 在线综合+亚洲+欧美中文字幕| 亚洲午夜免费电影| 欧美日韩视频一区二区| 日本sm残虐另类| 7777精品久久久大香线蕉| 蜜臀av一区二区| 国产日产欧美精品一区二区三区| 国产精品亚洲人在线观看| 欧美激情综合在线| 日本精品一级二级| 免费的国产精品| 国产三区在线成人av| 91免费在线看| 日本成人在线电影网| 久久久综合视频| 91麻豆国产在线观看| 毛片基地黄久久久久久天堂| 国产无人区一区二区三区| 99精品黄色片免费大全| 日韩中文字幕亚洲一区二区va在线| 精品区一区二区| 色综合久久中文字幕综合网 | 一区二区视频在线| 欧美日韩在线播放| 国产在线视频一区二区| 久久九九国产精品| 91欧美一区二区| 韩日精品视频一区| 一区二区理论电影在线观看| 精品剧情v国产在线观看在线| 成人国产精品免费观看动漫 | 亚洲超丰满肉感bbw| 日韩精品一区二区在线| 国产成人99久久亚洲综合精品| 欧美一级欧美一级在线播放| 亚洲女女做受ⅹxx高潮| 91影视在线播放| 成人欧美一区二区三区小说| 亚洲va韩国va欧美va精品| 久久精品二区亚洲w码| 国产99精品视频| 国产精品久久久久aaaa樱花| 国产成人免费xxxxxxxx| 国产精品国产a| 蜜臀精品久久久久久蜜臀| 国产精品女同互慰在线看| 国产麻豆日韩欧美久久| 亚洲成av人片一区二区三区| 国产精品欧美一区喷水| 精品国产乱子伦一区| 色婷婷国产精品综合在线观看| 国产精品77777| 国产伦精品一区二区三区免费迷|