本文源碼:GitHub·點這里 || GitEE·點這里
創(chuàng)新互聯(lián)長期為上1000家客戶提供的網(wǎng)站建設(shè)服務(wù),團隊從業(yè)經(jīng)驗10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為烏魯木齊企業(yè)提供專業(yè)的成都網(wǎng)站設(shè)計、成都網(wǎng)站制作,烏魯木齊網(wǎng)站改版等技術(shù)服務(wù)。擁有10多年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。
任何工具類的東西都是為了解決某個場景下的問題,比如redis緩存系統(tǒng)熱點數(shù)據(jù),ClickHouse解決海量數(shù)據(jù)的實時分析,MySQL關(guān)系型數(shù)據(jù)庫存儲結(jié)構(gòu)化數(shù)據(jù)。數(shù)據(jù)的存儲則需要設(shè)計對應(yīng)的表結(jié)構(gòu),清楚的表結(jié)構(gòu),有助于快速開發(fā)業(yè)務(wù),和理解系統(tǒng)。表結(jié)構(gòu)的設(shè)計通常從下面幾個方面考慮:業(yè)務(wù)場景、設(shè)計規(guī)范、表結(jié)構(gòu)、字段屬性、數(shù)據(jù)管理。
例如存儲用戶基礎(chǔ)信息數(shù)據(jù),通常都會下面幾個相關(guān)表結(jié)構(gòu):用戶信息表、單點登錄表、狀態(tài)管理表、支付賬戶表等。
存儲用戶三要素相關(guān)信息:姓名,手機號,身份證,登錄密碼,郵箱等。
CREATE TABLE `ms_user_center` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用戶ID',
`user_name` varchar(20) NOT NULL COMMENT '用戶名',
`real_name` varchar(20) DEFAULT NULL COMMENT '真實姓名',
`pass_word` varchar(32) NOT NULL COMMENT '密碼',
`phone` varchar(20) NOT NULL COMMENT '手機號',
`email` varchar(32) DEFAULT NULL COMMENT '郵箱',
`head_url` varchar(100) DEFAULT NULL COMMENT '用戶頭像URL',
`card_id` varchar(32) DEFAULT NULL COMMENT '身份證號',
`user_sex` int(1) DEFAULT '1' COMMENT '用戶性別:0-女,1-男',
`create_time` datetime DEFAULT NULL COMMENT '創(chuàng)建時間',
`update_time` datetime DEFAULT NULL COMMENT '更新時間',
`state` int(1) DEFAULT '1' COMMENT '是否可用,0-不可用,1-可用',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用戶表';
用意是在多個業(yè)務(wù)系統(tǒng)中,用戶登錄一次就可以訪問所有相互信任的業(yè)務(wù)子系統(tǒng),是聚合業(yè)務(wù)平臺常用的解決方案。
CREATE TABLE `ms_user_sso` (
`user_id` int(11) NOT NULL COMMENT '用戶ID',
`sso_id` varchar(32) NOT NULL COMMENT '單點信息編號ID',
`sso_code` varchar(32) NOT NULL COMMENT '單點登錄碼,唯一核心標(biāo)識',
`log_ip` varchar(32) DEFAULT NULL COMMENT '登錄IP地址',
`create_time` datetime DEFAULT NULL COMMENT '創(chuàng)建時間',
`update_time` datetime DEFAULT NULL COMMENT '更新時間',
`state` int(1) DEFAULT '1' COMMENT '是否可用,0-不可用,1-可用',
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用戶單點登錄表';
系統(tǒng)用戶在使用時候可能出現(xiàn)多個狀態(tài),例如賬戶凍結(jié)、密碼鎖定等,把狀態(tài)聚合到一起,可以更加方便的管理和驗證。
CREATE TABLE `ms_user_status` (
`user_id` int(11) NOT NULL COMMENT '用戶ID',
`account_status` int(1) DEFAULT '1' COMMENT '賬戶狀態(tài):0-凍結(jié),1-未凍結(jié)',
`real_name_status` int(1) DEFAULT '0' COMMENT '實名認(rèn)證狀態(tài):0-未實名,1-已實名',
`pay_pass_status` int(1) DEFAULT '0' COMMENT '支付密碼是否設(shè)置:0-未設(shè)置,1-設(shè)置',
`wallet_pass_status` int(1) DEFAULT '0' COMMENT '錢包密碼是否設(shè)置:0-未設(shè)置,1-設(shè)置',
`wallet_status` int(1) DEFAULT '1' COMMENT '錢包是否凍結(jié):0-凍結(jié),1-未凍結(jié)',
`email_status` int(1) DEFAULT '0' COMMENT '郵箱狀態(tài):0-未激活,1-激活',
`message_status` int(1) DEFAULT '1' COMMENT '短信提醒開啟:0-未開啟,1-開啟',
`letter_status` int(1) DEFAULT '1' COMMENT '站內(nèi)信提醒開啟:0-未開啟,1-開啟',
`emailmsg_status` int(1) DEFAULT '0' COMMENT '郵件提醒開啟:0-未開啟,1-開啟',
`create_time` datetime DEFAULT NULL COMMENT '創(chuàng)建時間',
`update_time` datetime DEFAULT NULL COMMENT '更新時間',
`state` int(1) DEFAULT '1' COMMENT '是否可用,0-不可用,1-可用',
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用戶狀態(tài)表';
用戶交易的核心表,存儲用戶相關(guān)的賬戶資金信息。
CREATE TABLE `ms_user_wallet` (
`wallet_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '錢包ID',
`user_id` int(11) NOT NULL COMMENT '用戶ID',
`wallet_pwd` varchar(32) DEFAULT NULL COMMENT '錢包密碼',
`total_account` decimal(20,2) DEFAULT '0.00' COMMENT '賬戶總額',
`usable_money` decimal(20,2) DEFAULT '0.00' COMMENT '可用余額',
`freeze_money` decimal(20,2) DEFAULT '0.00' COMMENT '凍結(jié)金額',
`freeze_time` datetime DEFAULT NULL COMMENT '凍結(jié)時間',
`thaw_time` datetime DEFAULT NULL COMMENT '解凍時間',
`create_time` datetime DEFAULT NULL COMMENT '創(chuàng)建時間',
`update_time` datetime DEFAULT NULL COMMENT '更新時間',
`state` int(1) DEFAULT '1' COMMENT '是否可用,0-不可用,1-可用',
PRIMARY KEY (`wallet_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用戶錢包';
通過上面幾個表設(shè)計的案例,可以看到表設(shè)計關(guān)聯(lián)到數(shù)據(jù)庫的各個方面知識:數(shù)據(jù)類型,索引,編碼,存儲引擎等。表設(shè)計是一個很大的命題,不過也遵循一個基本規(guī)范:三范式。
一范式
表的列的具有原子性,不可再分解,即列的信息,不能分解,關(guān)系型數(shù)據(jù)庫MySQL、Oracle等自動的滿足。
二范式
每個事實的數(shù)據(jù)記錄只會出現(xiàn)一次, 不會冗余, 通常設(shè)計一個主鍵來實現(xiàn)。
三范式
要求一個表中不包含已經(jīng)存在于其它表的非主鍵信息,例如部門和員工的信息,員工表包含部門表的主鍵ID,則可以關(guān)聯(lián)獲取相關(guān)信息,沒必要在員工表保存相關(guān)信息。
范式化設(shè)計
范式化結(jié)構(gòu)設(shè)計通常更新快,因為冗余數(shù)據(jù)較少,表結(jié)構(gòu)輕巧,也更好的寫入內(nèi)存中。但是查詢起來涉及到關(guān)聯(lián),代價非常高,非常損耗查詢性能。
反范式化設(shè)計
所有的數(shù)據(jù)都在一張表中,避免關(guān)聯(lián)查詢,索引的有效性更高,但是數(shù)據(jù)的冗余性極高。
上述的兩種設(shè)計方式在實際開發(fā)中都是不存在的,在實際開發(fā)中都是混合使用。比如匯總統(tǒng)計,緩存數(shù)據(jù),都會基于反范式化的設(shè)計。
合適的字段類型對于高性能來說非常重要,基本原則如下:簡單的類型占用資源更少;在可以正確存儲數(shù)據(jù)的情況下,選最小的數(shù)據(jù)類型。
TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,根據(jù)數(shù)據(jù)類型范圍合理選擇即可。
FLOAT、DOUBLE、DECIMAL,建議資金貨幣相關(guān)類型使用高精度DECIMAL存儲,或者把數(shù)據(jù)成倍擴大為整數(shù),采用BIGINT存儲,不過處理相對麻煩。
CHAR、VARCHAR,長度不確定建議采用VARCHAR存儲,不過VARCHAR類型需要額外開銷記錄字符串長度。CHAR適合存儲短字符,或者定長字符串,例如MD5的加密結(jié)構(gòu)。
DATETIME、TIMESTAMP,DATETIME保存大范圍的值,精度秒。TIMESTAMP以時間戳的格式,范圍相對較小,效率也相對較高,所以通常情況建議使用。
MySQL的字段類型有很多種,可以根據(jù)數(shù)據(jù)特性選擇合適的,這里只描述常見的幾種類型。
修改字段類型
ALTER TABLE ms_user_sso MODIFY state CHAR(1) DEFAULT '0' ;
ALTER TABLE ms_user_sso
MODIFY state INT(1) DEFAULT '1' COMMENT '狀態(tài):0不可用,1可用';
修改名稱位置
ALTER TABLE ms_user_sso
CHANGE log_ip login_ip VARCHAR(32) AFTER update_time ;
索引類型:主鍵索引,普通索引,唯一索引,組合索引,全文索引。這里演示普通索引的操作。MySQL的核心模塊,后續(xù)詳說。
添加索引
ALTER TABLE ms_user_wallet ADD INDEX user_id_index(user_id) ;
CREATE INDEX state_index ON ms_user_wallet(state) ;
查看索引
SHOW INDEX FROM ms_user_wallet;
刪除索引
DROP INDEX state_index ON ms_user_wallet ;
修改索引
不具有真正意義上的修改,可以把原有的索引刪除之后,再次添加索引。
用處:外鍵關(guān)聯(lián)的作用保證多個數(shù)據(jù)表的數(shù)據(jù)一致性和完整性,建表時先有主表,后有從表;刪除數(shù)據(jù)表,需要先刪從表,再刪主表。復(fù)雜場景不建議使用,實際開發(fā)中用的也不多。
添加外鍵
ALTER TABLE ms_user_wallet
ADD CONSTRAINT user_id_out_key FOREIGN KEY(user_id) REFERENCES ms_user_center(id) ;
刪除外鍵
ALTER TABLE ms_user_wallet DROP FOREIGN KEY user_id_out_key ;
DESC ms_user_status ;
SHOW CREATE TABLE ms_user_status ;
ALTER TABLE ms_user_status
ADD `delete_time` datetime DEFAULT NULL COMMENT '刪除時間' ;
ALTER TABLE ms_user_status DROP COLUMN delete_time ;
ALTER TABLE ms_user_center RENAME ms_user_info ;
SELECT VERSION() ; SHOW ENGINES ;
MySQL 5.6 支持的存儲引擎有InnoDB、MyISAM、Memory、Archive、CSV、BLACKHOLE等。一般默認(rèn)使用InnoDB,支持事務(wù)管理。該模塊MySQL核心,后續(xù)詳解。
數(shù)據(jù)量大的場景下,存儲引擎修改是一個難度極大的操作,容易會導(dǎo)致表的特性變動,引起各種后續(xù)反應(yīng),后續(xù)會詳說。
ALTER TABLE ms_user_sso ENGINE = MyISAM ;
表字符集默認(rèn)使用utf8,通用,無亂碼風(fēng)險,漢字3字節(jié),英文1字節(jié),utf8mb4是utf8的超集,有存儲4字節(jié)例如表情符號時使用。
SHOW VARIABLES LIKE 'character%';
ALTER TABLE ms_user_sso DEFAULT CHARACTER SET utf8mb4;
添加數(shù)據(jù)
INSERT INTO ms_user_sso (
user_id,sso_id,sso_code,create_time,update_time,login_ip,state
)
VALUES
(
'1','SSO7637267','SSO78631273612',
'2019-12-24 11:56:57','2019-12-24 11:57:01','127.0.0.1','1'
);
更新數(shù)據(jù)
UPDATE ms_user_sso SET
user_id = '1',sso_id = 'SSO20191224',sso_code = 'SSO20191224',
create_time = '2019-11-24 11:56:57',update_time = '2019-11-24 11:57:01',
login_ip = '127.0.0.1',state = '1'
WHERE user_id = '1';
查詢數(shù)據(jù)
一般情況下都是禁止使用 select* 操作。
SELECT user_id,sso_id,sso_code,create_time,update_time,login_ip,state
FROM ms_user_sso WHERE user_id = '1';
刪除數(shù)據(jù)
DELETE FROM ms_user_sso WHERE user_id = '2' ;
不帶where條件,就是刪除全部數(shù)據(jù)。原則上不允許該操作,優(yōu)化篇會詳解。TRUNCATE TABLE
也是清空表數(shù)據(jù),但是占用的資源相對較少。
這類加密算法,多用來做數(shù)據(jù)驗證操作,比如常見的密碼驗證。
SELECT MD5('cicada')='94454b1241ad2cfbd0c44efda1b6b6ba' ;
SELECT SHA('cicada')='0501746a2e4fd34e1d14015fc4d58309585edc7d';
SELECT PASSWORD('smile')='*B4FB95D86DCFC3F33A3852714DC742C77504479D' ;
安全性要求高的系統(tǒng),需要做三級等保,對數(shù)據(jù)的安全性極高,數(shù)據(jù)在存儲時必須加密入庫,取出時候需要解密,這些就需要可逆加密。
SELECT DECODE(ENCODE('123456','key_salt'),'key_salt') ;
SELECT AES_DECRYPT(AES_ENCRYPT('cicada','salt123'),'salt123');
上述數(shù)據(jù)安全的管理,也可以基于應(yīng)用系統(tǒng)的服務(wù)(代碼)層進行處理,相對專業(yè)的流程是從數(shù)據(jù)生成源頭處理,規(guī)避數(shù)據(jù)傳遞過程泄露,造成不必要的風(fēng)險。
GitHub·地址
https://github.com/cicadasmile/mysql-data-base
GitEE·地址
https://gitee.com/cicadasmile/mysql-data-base