mysql資料庫刷題1(mysql資料庫技術思考題6)

本文目錄一覽:

MySQL資料庫是一個多用戶,多線程的關係資料庫管理系統,其主要技術都包括哪些

在MySQL 8.0 之前, 我們假設一下有一條爛SQL,

mysqlselect * from t1 order by rand() ;

以多個線程在跑,導致CPU被跑滿了,其他的請求只能被阻塞進不來。那這種情況怎麼辦?

大概有以下幾種解決辦法:

設置max_execution_time 來阻止太長的讀SQL。那可能存在的問題是會把所有長SQL都給KILL 掉。有些必須要執行很長時間的也會被誤殺。

自己寫個腳本檢測這類語句,比如order by rand(), 超過一定時間用Kill query thread_id 給殺掉。

那能不能不要殺掉而讓他正常運行,但是又不影響其他的請求呢?

那mysql 8.0 引入的資源組(resource group,後面簡寫微RG)可以基本上解決這類問題。

比如我可以用 RG 來在SQL層面給他限制在特定的一個CPU核上,這樣我就不管他,讓他繼續運行,如果有新的此類語句,讓他排隊好了。

為什麼說基本呢?目前只能綁定CPU資源,其他的暫時不行。

那我來演示下如何使用RG。

創建一個資源組user_ytt. 這裡解釋下各個參數的含義,

type = user 表示這是一個用戶態線程,也就是前台的請求線程。如果type=system,表示後台線程,用來限制mysql自己的線程,比如Innodb purge thread,innodb read thread等等。

vcpu 代表cpu的邏輯核數,這裡0-1代表前兩個核被綁定到這個RG。可以用lscpu,top等列出自己的CPU相關信息。

thread_priority 設置優先順序。user 級優先順序設置大於0。

mysqlmysql create resource group user_ytt type = user  vcpu = 0-1 thread_priority=19 enable;Query OK, 0 rows affected (0.03 sec)

RG相關信息可以從 information_schema.resource_groups 系統表裡檢索。

mysqlmysql select * from information_schema.resource_groups;+———————+———————+————————+———-+—————–+| RESOURCE_GROUP_NAME | RESOURCE_GROUP_TYPE | RESOURCE_GROUP_ENABLED | VCPU_IDS | THREAD_PRIORITY |+———————+———————+————————+———-+—————–+| USR_default         | USER                |                      1 | 0-3      |               0 || SYS_default         | SYSTEM              |                      1 | 0-3      |               0 || user_ytt            | USER                |                      1 | 0-1      |              19 |+———————+———————+————————+———-+—————–+3 rows in set (0.00 sec)

我們來給語句select guid from t1 group by left(guid,8) order by rand() 賦予RG user_ytt。

mysql show processlist;+—–+—————–+———–+——+———+——-+————————+———————————————————–+| Id  | User            | Host      | db   | Command | Time  | State                  | Info                                                      |+—–+—————–+———–+——+———+——-+————————+———————————————————–+|   4 | event_scheduler | localhost | NULL | Daemon  | 10179 | Waiting on empty queue | NULL                                                      || 240 | root            | localhost | ytt  | Query   |   101 | Creating sort index    | select guid from t1 group by left(guid,8) order by rand() || 245 | root            | localhost | ytt  | Query   |     0 | starting               | show processlist                                          |+—–+—————–+———–+——+———+——-+————————+———————————————————–+3 rows in set (0.00 sec)

找到連接240對應的thread_id。

mysqlmysql select thread_id from performance_schema.threads where processlist_id = 240;+———–+| thread_id |+———–+|       278 |+———–+1 row in set (0.00 sec)

給這個線程278賦予RG user_ytt。沒報錯就算成功了。

mysqlmysql set resource group user_ytt for 278;Query OK, 0 rows affected (0.00 sec)

當然這個是在運維層面來做的,我們也可以在開發層面結合 MYSQL HINT 來單獨給這個語句賦予RG。比如:

mysqlmysql select /*+ resource_group(user_ytt) */guid from t1 group by left(guid,8) order by rand()….8388602 rows in set (4 min 46.09 sec)

RG的限制:

Linux 平台上需要開啟 CAPSYSNICE 特性。比如我機器上用systemd 給mysql 服務加上

systemctl edit mysql@80 [Service]AmbientCapabilities=CAP_SYS_NICE

mysql 線程池開啟後RG失效。

freebsd,solaris 平台thread_priority 失效。

目前只能綁定CPU,不能綁定其他資源。

如何從mysql資料庫中隨機獲取任意條數據?

隨機讀取可用newid(),取一條可用top 1

舉例:如在表test中隨機抽取一條未被讀取的數據,執行語句為:

select?top?1?*?from?test?order?by?newid()第一次執行結果:

第二次執行結果:

結論:兩次執行結果有可能一樣,也有可能不一樣,也就是實現了隨機的效果。

mysql資料庫報1-Can’t create/write to file ‘C:\WINDOWS\TEMP\#sql_1588_0.MYI'(Errcode:17)的錯誤。

問題分析:

1、C:\Windows\TEMP 文件夾許可權不夠,至少也要給出 USERS 組的可讀可寫許可權;

2、C:\Windows\TEMP 文件夾的磁碟滿了,文件寫不進去了,清空 TEMP 文件夾;

3、第三方限制(如殺毒軟體的限制)

1)你的伺服器裝了 MCAFEE 殺毒軟體,它的訪問保護禁止了 TEMP 文件可寫,修改訪問保護設置;

2)還是MCAFEE殺毒軟體的問題,解決步驟:按訪問掃描屬性 – 所有進程 – 檢測項 – 掃描文件(在寫入磁碟時 )勾去掉就好了。

mysql 數據類型的詳解

MySQL資料庫的表是一個二維表,由一個或多個數據列構成。

每個數據列都有它的特定類型,該類型決定了MySQL如何看待該列數據,我們可以把整型數值存放到字元類型的列中,MySQL則會把它看成字元串來處理。

MySQL中的列類型有三種:數值類、字元串類和日期/時間類。

從大類來看列類型和數值類型一樣,都是只有三種。但每種列類型都還可細分。

下面對各種列類型進行詳細介紹。

數值類的數據列類型

數值型的列類型包括整型和浮點型兩大類。

TINYINT:1位元組 非常小的正整數,帶符號:-128~127,不帶符號:0~255

SMALLINT:2位元組 小整數,帶符號:-32768~32767,不帶符號:0~65535

MEDIUMINT:3位元組 中等大小的整數,帶符號:-8388608~8388607,不帶符號:0~16777215

INT:4位元組 標準整數,帶符號:-2147483648~2147483647,不帶符號:0~4294967295

BIGINT:8位元組 大整數,帶符號:-9223372036854775808~9233372036854775807,不帶符號:0~18446744073709551615

FLOAT:4位元組 單精度浮點數,最小非零值:+-1.175494351E-38,最大非零值:+-3.402823466E+38

DOUBLE:8位元組 雙精度浮點數,最小非零值:+-2.2250738585072014E-308,最大非零值:+-1.7976931348623157E+308

DECIMAL:M+2位元組 以字元串形式表示的浮點數,它的取值範圍可變,由M和D的值決定。

MYSQL支持大量的列類型,它們可以被分為 3 類:數字類型、日期和時間類型以及字元串(字元)類型。這個章節首先給出可用類型的概述,並且總結各類型所需的存儲需求,然後提供各類型中的類型範疇更詳細的描述。概述有意地簡化了。更詳細的說明應該參考特寫列類型的附加信息,例如你能為其指定值的允許格式。

MySQL 支持的列類型在下面列出。下列代碼字母用於描述中:

M指出最大的顯示尺寸。最大的顯示尺寸長度為 255。D適用於浮點類型。指出跟隨在十進位小數點後的數字數量。最大可能值為 30,但不應大於M-2。

方括弧 (「[」and「]」) 指定可選的類型修飾部份。

注意,如果為一個列指定了ZEROFILL,MySQL 將自動為這個列添加UNSIGNED屬性。

警告:你應該知道當在兩個整數類型值中使用減法時,如有一個為UNSIGNED類型,那麼結果也是無符號的。查看章節6.3.5 Cast 函數。

TINYINT[(M)] [UNSIGNED] [ZEROFILL]-128到127。無符號的範圍是0到255。

BITBOOL它們是TINYINT(1)的同義詞。

SMALLINT[(M)] [UNSIGNED] [ZEROFILL]一個小整數。有符號的範圍是-32768到32767。無符號的範圍是0到65535。

MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]一個中等大小的整數。有符號的範圍是-8388608到8388607。無符號的範圍是0到16777215。

INT[(M)] [UNSIGNED] [ZEROFILL]一個正常大小的整數。有符號的範圍是-2147483648到2147483647。無符號的範圍是0到4294967295。

INTEGER[(M)] [UNSIGNED] [ZEROFILL]INT的同義詞。

BIGINT[(M)] [UNSIGNED] [ZEROFILL]一個大的整數。有符號的範圍是-9223372036854775808到9223372036854775807。無符號的範圍是0到18446744073709551615。

你應該知道的有關BIGINT列的一些事情:

BIGINT或DOUBLE值來完成的,因此你不應該使用大於9223372036854775807(63 bits) 的無符號大整數,除了位函數之外!如果你這樣做了,結果中的某些大數字可能會出錯,因為將BIGINT轉換成DOUBLE時產生了舍入錯誤。MySQL 4.0 在下列情況下可以處理BIGINT:

在一個BIGINT列中使用整數存儲一個大的無符號值。

在MIN(big_int_column)和MAX(big_int_column)中。

當兩個操作數都是整數時使用操作符 (+、-、*、等)。

通常你可以在一個BIGINT列中以字元串方式存儲的一個精確的整數。在這種情況下,MySQL 將執行一個字元串到數字的轉換,包括無 intermediate 的雙精度表示法。

當兩個參數均是整數值時,「-」、「+」和「*」將使用BIGINT運算!這就意味著,如果兩個大整數的乘積(或函數的結果返回整數)的結果大於9223372036854775807時,你可能會得到意想不到的結果。

FLOAT(precision) [UNSIGNED] [ZEROFILL]一個浮點型數字。

precision可以是=24作為一個單精度的浮點數字和介於 25 和 53 之間作為一個雙精度的浮點數字。這些類型與下面描述的FLOAT和DOUBLE類型相似。FLOAT(X)有與相應的FLOAT和DOUBLE類型同樣的範圍,但是顯示尺寸和十進位小數位數是未定義的。在 MySQL 3.23 中,它是一個真實的浮點值。而在 MySQL 早期的版本中,FLOAT(precision)通常有 2 小數位。 注意,由於在 MySQL 中所有的計算都是以雙精度執行的,所以使用FLOAT可能帶來一些意想不到的問題。查看章節A.5.6 解決沒有匹配行的問題。

FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]一個小的(單精度) 浮點數字。允許的值是-3.402823466E+38到-1.175494351E-38、0和1.175494351E-38到3.402823466E+38。如果UNSIGNED被指定,負值是不允許的。M是顯示寬度,D是小數位數。FLOAT沒有參數或有X= 24 的FLOAT(X)代表一個單精度的浮點數字。

DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]一個正常大小的(雙精度)浮上數字。允許的值是-1.7976931348623157E+308到-2.2250738585072014E-308、0和2.2250738585072014E-308到1.7976931348623157E+308。如果UNSIGNED被指定,負值是不允許的。M是顯示寬度,D是小數位數。DOUBLE沒胡參數或有 25 =X= 53 的FLOAT(X)代表一個雙精度的浮點數字。

DOUBLE PRECISION[(M,D)] [UNSIGNED] [ZEROFILL]

REAL[(M,D)] [UNSIGNED] [ZEROFILL]它們是DOUBLE同義詞。

DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]一個未壓縮(unpacked)的浮點數。運作如同一個CHAR列:「unpacked」 意味著數字是以一個字元串存儲的,值的每一位將使用一個字元。小數點並且對於負數,「-」符號不在M中計算(但是它們的空間是被保留的)。如果D是 0,值將沒有小數點或小數部份。DECIMAL值的最大範圍與DOUBLE一致,但是對於一個給定的DECIMAL列,實際的範圍可以被所選擇的M和D限制。如果UNSIGNED被指定,負值是不允許的。 如果D被忽略,預設為 0。如果M被忽略,預設為 10。 在 MySQL 3.23 以前,M參數必須包含符號與小數點所需的空間。

DEC[(M[,D])] [UNSIGNED] [ZEROFILL]

NUMERIC[(M[,D])] [UNSIGNED] [ZEROFILL]DECIMAL的同義詞。

DATE一個日期。支持的範圍是’1000-01-01’到’9999-12-31’。MySQL 以’YYYY-MM-DD’格式顯示DATE值,但是允許你以字元串或數字給一個DATE列賦值。查看章節6.2.2.2DATETIME、DATE和TIMESTAMP類型。

DATETIME一個日期和時間的組合。支持的範圍是’1000-01-01 00:00:00’到’9999-12-31 23:59:59’。MySQL 以’YYYY-MM-DD HH:MM:SS’格式顯示DATETIME值,但是允許你以字元串或數字給一個DATETIME列賦值。查看章節6.2.2.2DATETIME、DATE和TIMESTAMP類型。

TIMESTAMP[(M)]一個時間戳。範圍是’1970-01-01 00:00:00’到2037年間的任意時刻。 MySQL 4.0 和更早版本中,TIMESTAMP值是以YYYYMMDDHHMMSS、YYMMDDHHMMSS、YYYYMMDD或YYMMDD格式顯示的,它取決於M是否是14(或省略)、12、8或6,但是允許你以字元串或數字給一個TIMESTAMP列賦值。 從 MySQL 4.1 開始,TIMESTAMP以’YYYY-MM-DD HH:MM:DD’格式作為字元返回。如果你你希望以數字形式返回則必須在該時間戳欄位後加上 +0。不同的時間戳長度是不支持的。從 MySQL 4.0.12 開始,選項–new可以被用來使伺服器與 4.1 一樣運作。TIMESTAMP列有益於記錄一個INSERT或UPDATE操作的日期和時間,因為如果你自己沒有給它賦值,它將被自動地設置為最近一次操作的日期和時間。也可以通過給它賦一個NULL而使它設置為當前的日期和時間。查看章節6.2.2 Date 和 Time 類型。 參數M隻影響一個TIMESTAMP列的顯示格式;它的值總是佔用 4 個位元組存儲。 注意,當TIMESTAMP(M)列的M是 8 或 14 時,它返回的是數字而其它的TIMESTAMP(M)列返回的是字元串。這僅僅是為了可以可靠地轉儲並恢復到其它格式的表中。查看章節6.2.2.2DATETIME、DATE和TIMESTAMP類型。TIME一個時間。範圍是’-838:59:59’到’838:59:59’。MySQL 以’HH:MM:SS’格式顯示TIME值,但是允許你使用字元串或數字來給TIME列賦值。查看章節6.2.2.3TIME類型。YEAR[(2|4)]一個 2 或 4 位數字格式的年(預設為 4 位)。允許的值是1901到2155、0000(4 位年格式) 以及使用 2 位格式的 1970-2069 (70-69)。MySQL 以YYYY格式顯示YEAR值,但是允許你使用字元串或數字來給YEAR列賦值。(YEAR類型在 MySQL 3.22 之前不支持。) 查看章節6.2.2.4YEAR類型。

[NATIONAL] CHAR(M) [BINARY]一個定長的字元串,當存儲時,總是以空格填滿右邊到指定的長度。M的範圍是 0 到 255 (在 MySQL 3.23 版本之前為 1 到 255)。當該值被檢索時,尾部空格將被刪除。CHAR值根據預設的字符集進行忽略大小寫的排索與比較,除非指定了關鍵詞BINARY。NATIONAL CHAR(或短形式NCHAR) 是以 ANSI SQL 方式定義一個CHAR列,它將使用預設的字符集。這在 MySQL 中是默認的。

CHAR是CHARACTER的縮寫。 MySQL 允許以CHAR(0)類型建立一個列。一些老程序運行時必需一個列,卻又並不使用這個列的值,你就不得不為了適應它而建立該列,在這情況下,CHAR(0)將是很有益的。當需要一個列僅保存兩個值時:一個為CHAR(0)(該列沒有定義為NOT NULL),這將僅佔用一個比特位來存儲 2 個值:NULL或””。查看章節6.2.3.1CHAR和VARCHAR類型。CHAR這是CHAR(1)的同義詞。

[NATIONAL] VARCHAR(M) [BINARY]一個變長的字元串。注意:尾部的空格在存儲時將會被刪除(這與 ANSI SQL 約規不同)。M的範圍是 0 到 255 (在 MySQL 4.0.2 之前的版本中是 1 到 255)。

VARCHAR值以大小寫忽略方式進行排索與比較,除非關鍵詞BINARY被指定。查看章節6.5.3.1 隱式的列定義變化。VARCHAR是CHARACTER VARYING的縮寫。查看章節6.2.3.1CHAR和VARCHAR類型。

TINYBLOBTINYTEXT一個BLOB或TEXT列,最大長度為 255 (2^8 – 1) 個字元。查看章節6.5.3.1 隱式的列定義變化。查看章節6.2.3.2BLOB和TEXT類型。

BLOBTEXT一個BLOB或TEXT列,最大長度為 65535 (2^16 – 1) 個字元。查看章節6.5.3.1 隱式的列定義變化。查看章節6.2.3.2BLOB和TEXT類型。

MEDIUMBLOBMEDIUMTEXT一個BLOB或TEXT列,最大長度為 16777215 (2^24 – 1) 個字元。查看章節6.5.3.1 隱式的列定義變化。查看章節6.2.3.2BLOB和TEXT類型。

LONGBLOBLONGTEXT一個BLOB或TEXT列,最大長度為 4294967295 (2^32 – 1) 個字元。查看章節6.5.3.1 隱式的列定義變化。注意,由於伺服器/客戶端的協議以及 MyISAM 表通常有一個 16M 每通信包/錶行的限制,你仍然不能使用這個類型的整個範圍。查看章節6.2.3.2BLOB和TEXT類型。ENUM(‘value1′,’value2’,…)一個枚舉類型。一個僅能有一個值的字元串對象,這個值選自值列’value1’、’value2’、…、NULL或特殊的””出錯值。一個ENUM列可以有最大 65535 不同的值。查看章節6.2.3.3ENUM類型。SET(‘value1′,’value2’,…)一個集合。一個能有零個或更多個值的字元串對象,其中每個值必須選自值列’value1’、’value2’、…。一個SET列可以有最大 64 個成員。查看章節6.2.3.4SET類型。

MySQL 支持所有的 ANSI/ISO SQL92 數字類型。這些類型包括準確數字的數據類型(NUMERIC、DECIMAL、INTEGER和SMALLINT),也包括近似數字的數據類型(FLOAT、REAL和DOUBLE PRECISION)。關鍵詞INT是INTEGER的同義詞,關鍵詞DEC是DECIMAL的同義詞。

NUMERIC和DECIMAL類型被 MySQL 以同樣的類型實現,這在 SQL92 標準中是允許的。他們用於保存對準確精度有重要要求的值,例如與金錢有關的數據。當以它們中的之一聲明一個列時,精度和數值範圍可以(通常是)被指定;例如:

salary DECIMAL(5,2)

在這個例子中,5(精度(precision)) 代表重要的十進位數字的數目,2(數據範圍(scale)) 代表在小數點後的數字位數。在這種情況下,因此,salary列可以存儲的值範圍是從-99.99到99.99。(實際上 MySQL 在這個列中可以存儲的數值可以一直到999.99,因為它沒有存儲正數的符號)。

譯者註:

M 與D 對DECIMAL(M, D) 取值範圍的影響

類型說明 取值範圍(MySQL 3.23) 取值範圍(MySQL = 3.23)

DECIMAL(4, 1) -9.9 到 99.9 -999.9 到 9999.9

DECIMAL(5, 1) -99.9 到 999.9 -9999.9 到 99999.9

DECIMAL(6, 1) -999.9 到 9999.9 -99999.9 到 999999.9

DECIMAL(6, 2) -99.99 到 999.99 -9999.99 到 99999.99

DECIMAL(6, 3) -9.999 到 99.999 -999.999 到 9999.999

# 在MySQL 3.23 及以後的版本中,DECIMAL(M, D) 的取值範圍等於早期版本中的DECIMAL(M + 2, D) 的取值範圍。注釋結束:

在 ANSI/ISO SQL92 中,句法DECIMAL(p)等價於DECIMAL(p,0)。同樣的,在執行被允許決定值p的地方,句法DECIMAL等價於DECIMAL(p,0)。MySQL 目前還不支持DECIMAL/NUMERIC數據類型的這些變體形式中的任一種。一般來說這並不是一個嚴重的問題,通過明確地控制精度和數值範圍可以得到這些類型的主要功能益處。

DECIMAL和NUMERIC值是作為字元串存儲的,而不是作為二進位浮點數,以便保護這些值的十進位精確度。一個字元用於數值的每一位、小數點(如果scale 0) 和「-」符號(對於負值)。如果scale是 0,DECIMAL和NUMERIC值不包含小數點或小數部分。

DECIMAL和NUMERIC值的最大範圍與DOUBLE一致,但是對於一個給定的DECIMAL或NUMERIC列,它的實際範圍可制定該列時的precision或scale限制。當這樣的列被賦給了小數點的位數超過scale所指定的值時,該將根據scale進行四捨五入。當一個DECIMAL或NUMERIC列被賦與一個大小超過指定(或預設)的precisionandscale的限止範圍時,MySQL 以該列範圍的端點值存儲該值。

java習題:在MySQL資料庫建立一個學生信息表(學號,姓名,班級,成績),編程完成如下操作

use 庫名

go —–打開庫

create table 學生信息

(學號 int not null,

姓名 char(10) not null,

班級 nvarchar(20)

成績 int )

go —–這是建表

(1)insert into 學生信息(學號,姓名,班級,成績)

values(‘122153032′,’小靜’,『計應123』,’99’) —-這是插入記錄以此類推插入五條

(2)select *

from 學生信息

where 成績85 —–顯示成績大於85分的學生信息

(3) select *

from 學生信息

order by 成績desc —將表中的所有記錄,按照成績從小到大順序排列

能幫你的只有這些,望採納!

「春招系列」MySQL面試核心25問(附答案)

篇幅所限本文只寫了MySQL25題,像其他的Redis,SSM框架,演算法,計網等技術棧的面試題後面會持續更新,個人整理的1000餘道面試八股文會放在文末給大家白嫖,最近有面試需要刷題的同學可以直接翻到文末領取。

如果表使用自增主鍵,那麼每次插入新的記錄,記錄就會順序添加到當前索引節點的後續位置,當一頁寫滿,就會自動開闢一個新的頁。如果使用非自增主鍵(如果身份證號或學號等),由於每次插入主鍵的值近似於隨機,因此每次新紀錄都要被插到現有索引頁得中間某個位置, 頻繁的移動、分頁操作造成了大量的碎片,得到了不夠緊湊的索引結構,後續不得不通過OPTIMIZE TABLE(optimize table)來重建表並優化填充頁面。

Server層按順序執行sql的步驟為:

簡單概括:

可以分為服務層和存儲引擎層兩部分,其中:

服務層包括連接器、查詢緩存、分析器、優化器、執行器等 ,涵蓋MySQL的大多數核心服務功能,以及所有的內置函數(如日期、時間、數學和加密函數等),所有跨存儲引擎的功能都在這一層實現,比如存儲過程、觸發器、視圖等。

存儲引擎層負責數據的存儲和提取 。其架構模式是插件式的,支持InnoDB、MyISAM、Memory等多個存儲引擎。現在最常用的存儲引擎是InnoDB,它從MySQL 5.5.5版本開始成為了默認的存儲引擎。

Drop、Delete、Truncate都表示刪除,但是三者有一些差別:

Delete 用來刪除表的全部或者一部分數據行,執行Delete之後,用戶需要提交(commmit)或者回滾(rollback)來執行刪除或者撤銷刪除,會觸發這個表上所有的delete觸發器。

Truncate 刪除表中的所有數據,這個操作不能回滾,也不會觸發這個表上的觸發器,TRUNCATE比Delete更快,佔用的空間更小。

Drop 命令從資料庫中刪除表,所有的數據行,索引和許可權也會被刪除,所有的DML觸發器也不會被觸發,這個命令也不能回滾。

因此,在不再需要一張表的時候,用Drop;在想刪除部分數據行時候,用Delete;在保留表而刪除所有數據的時候用Truncate。

隔離級別臟讀不可重複讀幻影讀 READ-UNCOMMITTED 未提交讀 READ-COMMITTED 提交讀 REPEATABLE-READ 重複讀 SERIALIZABLE 可串列化讀

MySQL InnoDB 存儲引擎的默認支持的隔離級別是 REPEATABLE-READ (可重讀)

這裡需要注意的是 :與 SQL 標準不同的地方在於InnoDB 存儲引擎在 REPEATABLE-READ(可重讀)事務隔離級別 下使用的是 Next-Key Lock 鎖 演算法,因此可以避免幻讀的產生,這與其他資料庫系統(如 SQL Server)是不同的。所以 說InnoDB 存儲引擎的默認支持的隔離級別是 REPEATABLE-READ(可重讀) 已經可以完全保證事務的隔離性要 求,即達到了 SQL標準的SERIALIZABLE(可串列化)隔離級別。

因為隔離級別越低,事務請求的鎖越少,所以大部分資料庫系統的隔離級別都是READ-COMMITTED(讀取提交內 容):,但是你要知道的是InnoDB 存儲引擎默認使用 REPEATABLE-READ(可重讀)並不會有任何性能損失 。

InnoDB 存儲引擎在分散式事務 的情況下一般會用到SERIALIZABLE(可串列化)隔離級別。

主要原因:B+樹只要遍歷葉子節點就可以實現整棵樹的遍歷,而且在資料庫中基於範圍的查詢是非常頻繁的,而B樹只能中序遍歷所有節點,效率太低。

文件與資料庫都是需要較大的存儲,也就是說,它們都不可能全部存儲在內存中,故需要存儲到磁碟上。而所謂索引,則為了數據的快速定位與查找,那麼索引的結構組織要盡量減少查找過程中磁碟I/O的存取次數,因此B+樹相比B樹更為合適。資料庫系統巧妙利用了局部性原理與磁碟預讀原理,將一個節點的大小設為等於一個頁,這樣每個節點只需要一次I/O就可以完全載入,而紅黑樹這種結構,高度明顯要深的多,並且由於邏輯上很近的節點(父子)物理上可能很遠,無法利用局部性。

最重要的是,B+樹還有一個最大的好處:方便掃庫。

B樹必須用中序遍歷的方法按序掃庫,而B+樹直接從葉子結點挨個掃一遍就完了,B+樹支持range-query非常方便,而B樹不支持,這是資料庫選用B+樹的最主要原因。

B+樹查找效率更加穩定,B樹有可能在中間節點找到數據,穩定性不夠。

B+tree的磁碟讀寫代價更低:B+tree的內部結點並沒有指向關鍵字具體信息的指針(紅色部分),因此其內部結點相對B 樹更小。如果把所有同一內部結點的關鍵字存放在同一塊盤中,那麼盤塊所能容納的關鍵字數量也越多。一次性讀入內存中的需要查找的關鍵字也就越多,相對來說IO讀寫次數也就降低了;

B+tree的查詢效率更加穩定:由於內部結點並不是最終指向文件內容的結點,而只是葉子結點中關鍵字的索引,所以,任何關鍵字的查找必須走一條從根結點到葉子結點的路。所有關鍵字查詢的路徑長度相同,導致每一個數據的查詢效率相當;

視圖是一種虛擬的表,通常是有一個表或者多個表的行或列的子集,具有和物理表相同的功能 游標是對查詢出來的結果集作為一個單元來有效的處理。一般不使用游標,但是需要逐條處理數據的時候,游標顯得十分重要。

而在 MySQL 中,恢復機制是通過回滾日誌(undo log)實現的,所有事務進行的修改都會先記錄到這個回滾日誌中,然後在對資料庫中的對應行進行寫入。當事務已經被提交之後,就無法再次回滾了。

回滾日誌作用:1)能夠在發生錯誤或者用戶執行 ROLLBACK 時提供回滾相關的信息 2) 在整個系統發生崩潰、資料庫進程直接被殺死後,當用戶再次啟動資料庫進程時,還能夠立刻通過查詢回滾日誌將之前未完成的事務進行回滾,這也就需要回滾日誌必須先於數據持久化到磁碟上,是我們需要先寫日誌後寫資料庫的主要原因。

InnoDB

MyISAM

總結

資料庫並發會帶來臟讀、幻讀、丟棄更改、不可重複讀這四個常見問題,其中:

臟讀 :在第一個修改事務和讀取事務進行的時候,讀取事務讀到的數據為100,這是修改之後的數據,但是之後該事務滿足一致性等特性而做了回滾操作,那麼讀取事務得到的結果就是臟數據了。

幻讀 :一般是T1在某個範圍內進行修改操作(增加或者刪除),而T2讀取該範圍導致讀到的數據是修改之間的了,強調範圍。

丟棄修改 :兩個寫事務T1 T2同時對A=0進行遞增操作,結果T2覆蓋T1,導致最終結果是1 而不是2,事務被覆蓋

不可重複讀 :T2 讀取一個數據,然後T1 對該數據做了修改。如果 T2 再次讀取這個數據,此時讀取的結果和第一次讀取的結果不同。

第一個事務首先讀取var變數為50,接著準備更新為100的時,並未提交,第二個事務已經讀取var為100,此時第一個事務做了回滾。最終第二個事務讀取的var和資料庫的var不一樣。

T1 讀取某個範圍的數據,T2 在這個範圍內插入新的數據,T1 再次讀取這個範圍的數據,此時讀取的結果和和第一次讀取的結果不同。

T1 和 T2 兩個事務都對一個數據進行修改,T1 先修改,T2 隨後修改,T2 的修改覆蓋了 T1 的修改。例如:事務1讀取某表中的數據A=50,事務2也讀取A=50,事務1修改A=A+50,事務2也修改A=A+50,最終結果A=100,事務1的修改被丟失。

T2 讀取一個數據,T1 對該數據做了修改。如果 T2 再次讀取這個數據,此時讀取的結果和第一次讀取的結果不同。

悲觀鎖,先獲取鎖,再進行業務操作,一般就是利用類似 SELECT … FOR UPDATE 這樣的語句,對數據加鎖,避免其他事務意外修改數據。當資料庫執行SELECT … FOR UPDATE時會獲取被select中的數據行的行鎖,select for update獲取的行鎖會在當前事務結束時自動釋放,因此必須在事務中使用。

樂觀鎖,先進行業務操作,只在最後實際更新數據時進行檢查數據是否被更新過。Java 並發包中的 AtomicFieldUpdater 類似,也是利用 CAS 機制,並不會對數據加鎖,而是通過對比數據的時間戳或者版本號,來實現樂觀鎖需要的版本判斷。

分庫與分表的目的在於,減小資料庫的單庫單表負擔,提高查詢性能,縮短查詢時間。

通過分表 ,可以減少資料庫的單表負擔,將壓力分散到不同的表上,同時因為不同的表上的數據量少了,起到提高查詢性能,縮短查詢時間的作用,此外,可以很大的緩解表鎖的問題。分表策略可以歸納為垂直拆分和水平拆分:

水平分表 :取模分表就屬於隨機分表,而時間維度分表則屬於連續分表。如何設計好垂直拆分,我的建議:將不常用的欄位單獨拆分到另外一張擴展表. 將大文本的欄位單獨拆分到另外一張擴展表, 將不經常修改的欄位放在同一張表中,將經常改變的欄位放在另一張表中。對於海量用戶場景,可以考慮取模分表,數據相對比較均勻,不容易出現熱點和並發訪問的瓶頸。

庫內分表 ,僅僅是解決了單表數據過大的問題,但並沒有把單表的數據分散到不同的物理機上,因此並不能減輕 MySQL 伺服器的壓力,仍然存在同一個物理機上的資源競爭和瓶頸,包括 CPU、內存、磁碟 IO、網路帶寬等。

分庫與分錶帶來的分散式困境與應對之策 數據遷移與擴容問題—-一般做法是通過程序先讀出數據,然後按照指定的分表策略再將數據寫入到各個分表中。分頁與排序問題—-需要在不同的分表中將數據進行排序並返回,並將不同分表返回的結果集進行匯總和再次排序,最後再返回給用戶。

不可重複讀的重點是修改,幻讀的重點在於新增或者刪除。

視圖是虛擬的表,與包含數據的表不一樣,視圖只包含使用時動態檢索數據的查詢;不包含任何列或數據。使用視圖可以簡化複雜的 sql 操作,隱藏具體的細節,保護數據;視圖創建後,可以使用與表相同的方式利用它們。

視圖不能被索引,也不能有關聯的觸發器或默認值,如果視圖本身內有order by 則對視圖再次order by將被覆蓋。

創建視圖:create view xxx as xxxx

對於某些視圖比如未使用聯結子查詢分組聚集函數Distinct Union等,是可以對其更新的,對視圖的更新將對基表進行更新;但是視圖主要用於簡化檢索,保護數據,並不用於更新,而且大部分視圖都不可以更新。

B+tree的磁碟讀寫代價更低,B+tree的查詢效率更加穩定 資料庫索引採用B+樹而不是B樹的主要原因:B+樹只要遍歷葉子節點就可以實現整棵樹的遍歷,而且在資料庫中基於範圍的查詢是非常頻繁的,而B樹只能中序遍歷所有節點,效率太低。

B+樹的特點

在最頻繁使用的、用以縮小查詢範圍的欄位,需要排序的欄位上建立索引。不宜:1)對於查詢中很少涉及的列或者重複值比較多的列 2)對於一些特殊的數據類型,不宜建立索引,比如文本欄位(text)等。

如果一個索引包含(或者說覆蓋)所有需要查詢的欄位的值,我們就稱 之為「覆蓋索引」。

我們知道在InnoDB存儲引 擎中,如果不是主鍵索引,葉子節點存儲的是主鍵+列值。最終還是要「回表」,也就是要通過主鍵再查找一次,這樣就 會比較慢。覆蓋索引就是把要查詢出的列和索引是對應的,不做回表操作!

舉例 :

學號姓名性別年齡系別專業 20020612李輝男20計算機軟體開發 20060613張明男18計算機軟體開發 20060614王小玉女19物理力學 20060615李淑華女17生物動物學 20060616趙靜男21化學食品化學 20060617趙靜女20生物植物學

主鍵為候選鍵的子集,候選鍵為超鍵的子集,而外鍵的確定是相對於主鍵的。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/280545.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-21 13:05
下一篇 2024-12-21 13:05

相關推薦

  • 如何修改mysql的埠號

    本文將介紹如何修改mysql的埠號,方便開發者根據實際需求配置對應埠號。 一、為什麼需要修改mysql埠號 默認情況下,mysql使用的埠號是3306。在某些情況下,我們需…

    編程 2025-04-29
  • Python 常用資料庫有哪些?

    在Python編程中,資料庫是不可或缺的一部分。隨著互聯網應用的不斷擴大,處理海量數據已成為一種趨勢。Python有許多成熟的資料庫管理系統,接下來我們將從多個方面介紹Python…

    編程 2025-04-29
  • openeuler安裝資料庫方案

    本文將介紹在openeuler操作系統中安裝資料庫的方案,並提供代碼示例。 一、安裝MariaDB 下面介紹如何在openeuler中安裝MariaDB。 1、更新軟體源 sudo…

    編程 2025-04-29
  • Python操作MySQL

    本文將從以下幾個方面對Python操作MySQL進行詳細闡述: 一、連接MySQL資料庫 在使用Python操作MySQL之前,我們需要先連接MySQL資料庫。在Python中,我…

    編程 2025-04-29
  • 資料庫第三範式會有刪除插入異常

    如果沒有正確設計資料庫,第三範式可能導致刪除和插入異常。以下是詳細解釋: 一、什麼是第三範式和範式理論? 範式理論是關係資料庫中的一個規範化過程。第三範式是範式理論中的一種常見形式…

    編程 2025-04-29
  • MySQL遞歸函數的用法

    本文將從多個方面對MySQL遞歸函數的用法做詳細的闡述,包括函數的定義、使用方法、示例及注意事項。 一、遞歸函數的定義 遞歸函數是指在函數內部調用自身的函數。MySQL提供了CRE…

    編程 2025-04-29
  • leveldb和unqlite:兩個高性能的資料庫存儲引擎

    本文將介紹兩款高性能的資料庫存儲引擎:leveldb和unqlite,並從多個方面對它們進行詳細的闡述。 一、leveldb:輕量級的鍵值存儲引擎 1、leveldb概述: lev…

    編程 2025-04-28
  • Python怎麼導入資料庫

    Python是一種高級編程語言。它具有簡單、易讀的語法和廣泛的庫,讓它成為一個靈活和強大的工具。Python的資料庫連接類型可以多種多樣,其中包括MySQL、Oracle、Post…

    編程 2025-04-28
  • MySQL bigint與long的區別

    本文將從數據類型定義、存儲空間、數據範圍、計算效率、應用場景五個方面詳細闡述MySQL bigint與long的區別。 一、數據類型定義 bigint在MySQL中是一種有符號的整…

    編程 2025-04-28
  • MySQL左連接索引不生效問題解決

    在MySQL資料庫中,經常會使用左連接查詢操作,但是左連接查詢中索引不生效的情況也比較常見。本文將從多個方面探討MySQL左連接索引不生效問題,並給出相應的解決方法。 一、索引的作…

    編程 2025-04-28

發表回復

登錄後才能評論