1、情況一:MySQL的錯(cuò)誤日志文件(安裝目錄\MYOA\data5\機(jī)器名.err)會(huì)記錄如下內(nèi)容:
浦北網(wǎng)站建設(shè)公司成都創(chuàng)新互聯(lián)公司,浦北網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為浦北數(shù)千家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站建設(shè)公司要多少錢(qián),請(qǐng)找那個(gè)售后服務(wù)好的浦北做網(wǎng)站的公司定做!
InnoDB: Reading tablespace information from the .ibd files...
InnoDB: Error: trying to add tablespace 460 of name '.\td_oa\flow_data_35.ibd'
InnoDB: to the tablespace memory cache, but tablespace
InnoDB: 460 of name '.\td_oa\exam_data.ibd' already exists in the tablespace
解決方法:
1)剪切出安裝目錄\MYOA\data5\TD_OA的flow_data_35.ibd和flow_data_35.frm兩個(gè)文件;
2)啟動(dòng)MySQL5_OA服務(wù),使用備份的flow_data_35.sql導(dǎo)入到TD_OA庫(kù)中。如果提示flow_data_35表已經(jīng)存在不能導(dǎo)入,則繼續(xù)按后續(xù)步驟執(zhí)行;
3)在data5下手動(dòng)建立tmp目錄;
4)使用MySQL管理工具或MySQL命令行程序在tmp下建立名稱(chēng)為flow_data_35的表(包含一個(gè)字段即可);
5)將tmp下的flow_data_35.frm和flow_data_35.ibd拷貝到安裝目錄\MYOA\data5\TD_OA目錄下;
6)在MySQL管理工具或MySQL命令行程序中,進(jìn)入TD_OA庫(kù),使用“drop table flow_data_35;”命令清除公共表空間中殘留的flow_data_35表的相關(guān)信息;
7)進(jìn)入tmp庫(kù),刪掉flow_data_35表;
8)使用備份的flow_data_35.sql導(dǎo)入到TD_OA庫(kù)中;
9)如果還有其他表存在該問(wèn)題,可重復(fù)執(zhí)行4至8步驟。
2、情況二:MySQL的錯(cuò)誤日志文件(安裝目錄\MYOA\data5\機(jī)器名.err)會(huì)記錄如下內(nèi)容:
130409 15:54:31 [Note] Plugin 'FEDERATED' is disabled.
130409 15:54:31 InnoDB: The InnoDB memory heap is disabled
130409 15:54:31 InnoDB: Mutexes and rw_locks use Windows interlocked functions
130409 15:54:31 InnoDB: Compressed tables use zlib 1.2.3
130409 15:54:32 InnoDB: Initializing buffer pool, size = 1023.0M
InnoDB: VirtualAlloc(1086849024 bytes) failed; Windows error 8
130409 15:54:32 InnoDB: Completed initialization of buffer pool
130409 15:54:32 InnoDB: Fatal error: cannot allocate memory for the buffer pool
130409 15:54:32 [ERROR] Plugin 'InnoDB' init function returned error.
130409 15:54:32 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.
130409 15:54:32 [ERROR] Unknown/unsupported storage engine: Innodb
130409 15:54:32 [ERROR] Aborting
解決方法:
此情況出現(xiàn)的原因是myoa\mysql5\my.ini中innodb_buffer_pool_size的值太大,OA服務(wù)器操作系統(tǒng)不支持所致。改小后再啟動(dòng)mysql5_OA服務(wù)即可,一般保持和數(shù)據(jù)庫(kù)大小一致。數(shù)據(jù)庫(kù)大小即是myoa/data5的大小。
3、情況三:mysql服務(wù)啟動(dòng)不了,事件查看器中顯示:The syntax
'--log-slow-queries' is deprecated and will be removed in a future
release. Please use '--slow-query-log'/'--slow-query-log-file' instead.
解決方法:安裝目錄\MYOA\data5下的ibdata1、ib_logfile0、ib_logfile1文件屬性被設(shè)置為只讀導(dǎo)致,取消只讀控制,重啟mysql5_OA服務(wù)即可。
4、情況四:MySQL的錯(cuò)誤日志文件(data5\機(jī)器名.err)會(huì)記錄如下內(nèi)容:InnoDB: No valid checkpoint found.
解決方法:此問(wèn)題找不到檢查點(diǎn),數(shù)據(jù)庫(kù)是無(wú)效的,此種情況,只能用熱備份數(shù)據(jù)恢復(fù)。
5、以上四種情況,是2013版OA系統(tǒng)目前比較常見(jiàn)的mysql服務(wù)啟動(dòng)不了的現(xiàn)象和解決辦法,大家可作參考,其他情況的話,再具體分析處理。
6、分析思路總結(jié):遇到mysql5_OA服務(wù)啟動(dòng)不了的情況,首先查看myoa\data5下的錯(cuò)誤日志文件,根據(jù)日志中的具體內(nèi)容進(jìn)行具體分析。
7、2013版MYSQL服務(wù)啟動(dòng)不了(可以嘗試強(qiáng)制啟動(dòng)mysql服務(wù))方法如下:
1)打開(kāi)\MYOA\mysql5\my.ini,去掉innodb_force_recovery=1前邊的注釋。
2)啟動(dòng)MySQL5_OA服務(wù),此時(shí)MySQL處于只讀狀態(tài),可以導(dǎo)出,不可寫(xiě)入。如果仍不能啟動(dòng),可以嘗試將innodb_force_recovery修改為2、3、4、5、6等,直到可以啟動(dòng)為止。
3)使用MySQL管理工具,將TD_OA等相關(guān)的數(shù)據(jù)庫(kù)導(dǎo)出為SQL文件。
4)停止MySQL5_OA服務(wù),刪除TD_OA下的所有文件、ibdata1、ib_logfile0、ib_logfile1等文件。
5)打開(kāi)\MYOA\mysql5\my.ini,在innodb_force_recovery=1前邊加上#號(hào),將該項(xiàng)注釋掉。
6)啟動(dòng)MySQL5_OA服務(wù),然后導(dǎo)入此前備份的SQL文件。
7)檢查數(shù)據(jù)庫(kù),將無(wú)法通過(guò)該方法恢復(fù)的數(shù)據(jù)表,通過(guò)之前自動(dòng)備份的SQL文件進(jìn)行恢復(fù)。
MySQL 的 Binlog 記錄著 MySQL 數(shù)據(jù)庫(kù)的所有變更信息,了解 Binlog 的結(jié)構(gòu)可以幫助我們解析Binlog,甚至對(duì) Binlog 進(jìn)行一些修改,或者說(shuō)是“篡改”,例如實(shí)現(xiàn)類(lèi)似于 Oracle 的 flashback 的功能,恢復(fù)誤刪除的記錄,把 update 的記錄再還原回去等。本文將帶您探討一下這些神奇功能的實(shí)現(xiàn),您會(huì)發(fā)現(xiàn)比您想象地要簡(jiǎn)單得多。本文指的 Binlog 是 ROW 模式的 Binlog,這也是 MySQL 8 里的默認(rèn)模式,STATEMENT 模式因?yàn)槭褂弥杏泻芏嘞拗?,現(xiàn)在用得越來(lái)越少了。
Binlog 由事件(event)組成,請(qǐng)注意是事件(event)不是事務(wù)(transaction),一個(gè)事務(wù)可以包含多個(gè)事件。事件描述對(duì)數(shù)據(jù)庫(kù)的修改內(nèi)容。
現(xiàn)在我們已經(jīng)了解了 Binlog 的結(jié)構(gòu),我們可以試著修改 Binlog 里的數(shù)據(jù)。例如前面舉例的 Binlog 刪除了一條記錄,我們可以試著把這條記錄恢復(fù),Binlog 里面有個(gè)刪除行(DELETE_ROWS_EVENT)的事件,就是這個(gè)事件刪除了記錄,這個(gè)事件和寫(xiě)行(WRITE_ROWS_EVENT)的事件的數(shù)據(jù)結(jié)構(gòu)是完全一樣的,只是刪除行事件的類(lèi)型是 32,寫(xiě)行事件的類(lèi)型是 30,我們把對(duì)應(yīng)的 Binlog 位置的 32 改成 30 即可把已經(jīng)刪除的記錄再插入回去。從前面的 “show binlog events” 里面可看到這個(gè) DELETE_ROWS_EVENT 是從位置 378 開(kāi)始的,這里的位置就是 Binlog 文件的實(shí)際位置(以字節(jié)為單位)。從事件(event)的結(jié)構(gòu)里面可以看到 type_code 是在 event 的第 5 個(gè)字節(jié),我們寫(xiě)個(gè) Python 小程序把把第383(378+5=383)字節(jié)改成 30 即可。當(dāng)然您也可以用二進(jìn)制編輯工具來(lái)改。
找出 Binlog 中的大事務(wù)
由于 ROW 模式的 Binlog 是每一個(gè)變更都記錄一條日志,因此一個(gè)簡(jiǎn)單的 SQL,在 Binlog 里可能會(huì)產(chǎn)生一個(gè)巨無(wú)霸的事務(wù),例如一個(gè)不帶 where 的 update 或 delete 語(yǔ)句,修改了全表里面的所有記錄,每條記錄都在 Binlog 里面記錄一次,結(jié)果是一個(gè)巨大的事務(wù)記錄。這樣的大事務(wù)經(jīng)常是產(chǎn)生麻煩的根源。我的一個(gè)客戶有一次向我抱怨,一個(gè) Binlog 前滾,滾了兩天也沒(méi)有動(dòng)靜,我把那個(gè) Binlog 解析了一下,發(fā)現(xiàn)里面有個(gè)事務(wù)產(chǎn)生了 1.4G 的記錄,修改了 66 萬(wàn)條記錄!下面是一個(gè)簡(jiǎn)單的找出 Binlog 中大事務(wù)的 Python 小程序,我們知道用 mysqlbinlog 解析的 Binlog,每個(gè)事務(wù)都是以 BEGIN 開(kāi)頭,以 COMMIT 結(jié)束。我們找出 BENGIN 前面的 “# at” 的位置,檢查 COMMIT 后面的 “# at” 位置,這兩個(gè)位置相減即可計(jì)算出這個(gè)事務(wù)的大小,下面是這個(gè) Python 程序的例子。
切割 Binlog 中的大事務(wù)
對(duì)于大的事務(wù),MySQL 會(huì)把它分解成多個(gè)事件(注意一個(gè)是事務(wù) TRANSACTION,另一個(gè)是事件 EVENT),事件的大小由參數(shù) binlog-row-event-max-size 決定,這個(gè)參數(shù)默認(rèn)是 8K。因此我們可以把若干個(gè)事件切割成一個(gè)單獨(dú)的略小的事務(wù)
ROW 模式下,即使我們只更新了一條記錄的其中某個(gè)字段,也會(huì)記錄每個(gè)字段變更前后的值,這個(gè)行為是 binlog_row_image 參數(shù)控制的,這個(gè)參數(shù)有 3 個(gè)值,默認(rèn)為 FULL,也就是記錄列的所有修改,即使字段沒(méi)有發(fā)生變更也會(huì)記錄。這樣我們就可以實(shí)現(xiàn)類(lèi)似 Oracle 的 flashback 的功能,我個(gè)人估計(jì) MySQL 未來(lái)的版本從可能會(huì)基于 Binlog 推出這樣的功能。
了解了 Binlog 的結(jié)構(gòu),再加上 Python 這把瑞士軍刀,我們還可以實(shí)現(xiàn)很多功能,例如我們可以統(tǒng)計(jì)哪個(gè)表被修改地最多?我們還可以把 Binlog 切割成一段一段的,然后再重組,可以靈活地進(jìn)行 MySQL 數(shù)據(jù)庫(kù)的修改和遷移等工作。
怎么樣對(duì)MySQL中的事件進(jìn)行調(diào)度
一、概述
事件調(diào)度器是在 MySQL 5.1 中新增的另一個(gè)特色功能,可以作為定時(shí)任務(wù)調(diào)度器,取代部分原先只能用操作系統(tǒng)任務(wù)調(diào)度器才能完成的定時(shí)功能。例如,Linux 中的 crontabe 只能精確到每分鐘執(zhí)行一次,而 MySQL 的事件調(diào)度器則可以實(shí)現(xiàn)每秒鐘執(zhí)行一個(gè)任務(wù),這在一些對(duì)實(shí)時(shí)性要求較高的環(huán)境下就非常實(shí)用了。
事件調(diào)度器是定時(shí)觸發(fā)執(zhí)行的,在這個(gè)角度上也可以稱(chēng)作是"臨時(shí)的觸發(fā)器"。觸發(fā)器只是針對(duì)某個(gè)表產(chǎn)生的事件執(zhí)行一些語(yǔ)句,而事件調(diào)度器則是在某一個(gè)(間隔)時(shí)間執(zhí)行一些語(yǔ)句。事件是由一個(gè)特定的線程來(lái)管理的,也就是所謂的"事件調(diào)度器"。啟用事件調(diào)度器后,擁有 SUPER 權(quán)限的賬戶執(zhí)行 SHOW PROCESSLIST 就可以看到這個(gè)線程了。通過(guò)設(shè)定全局變量event_scheduler 的值即可動(dòng)態(tài)的控制事件調(diào)度器是否啟用。
復(fù)制代碼 代碼如下:
(root:localhost:)test SET GLOBAL event_scheduler = ON;
(root:localhost:)test show processlist\G
*************************** 4. row ***************************
Id: 46147
User: event_scheduler
Host: localhost
db: NULL
Command: Daemon
Time: 1
State: Waiting on empty queue
Info: NULL
如上,該線程的所有者是 event_scheduler。
二、應(yīng)用案例
本案例是利用 event scheduler 的特性,每秒鐘調(diào)用一次存儲(chǔ)過(guò)程,用于判斷 SLAVE 是否正常運(yùn)行,如果發(fā)現(xiàn) SLAVE 關(guān)閉了,忽略 0 次錯(cuò)誤,然后重新啟動(dòng) SLAVE。
首先創(chuàng)建存儲(chǔ)過(guò)程
delimiter //
復(fù)制代碼 代碼如下:
create procedure `Slave_Monitor`()
begin
SELECT VARIABLE_VALUE INTO @SLAVE_STATUS
FROM information_schema.GLOBAL_STATUS
WHERE VARIABLE_NAME='SLAVE_RUNNING';
IF ('ON' != @SLAVE_STATUS) THEN
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=0;
SLAVE START;
END IF;
end; //
delimiter ;
由于存儲(chǔ)過(guò)程中無(wú)法調(diào)用類(lèi)似 SHOW SLAVE STATUS 這樣的語(yǔ)句,因此無(wú)法得到確切的復(fù)制錯(cuò)誤信息和錯(cuò)誤代碼,不能進(jìn)一步的處理 SLAVE 停止的各種情況。
接著,創(chuàng)建任務(wù)
復(fù)制代碼 代碼如下:
CREATE EVENT IF NOT EXISTS `Slave_Monitor`
ON SCHEDULE EVERY 5 SECOND
ON COMPLETION PRESERVE
DO
CALL Slave_Monitor();
創(chuàng)建了一個(gè)任務(wù),每 5秒鐘 執(zhí)行一次,任務(wù)結(jié)束后依舊保留該任務(wù),而不是刪除。當(dāng)然了,在本例中的任務(wù)不會(huì)結(jié)束,除非將它手動(dòng)禁止了。
如果在運(yùn)行中想要臨時(shí)關(guān)閉一下某個(gè)任務(wù),執(zhí)行 ALTER EVENT 語(yǔ)句即可:
復(fù)制代碼 代碼如下:
(root:localhost:)test alter event `Slave_Monitor` ON
COMPLETION PRESERVE DISABLE;
(root:localhost:)test alter event `Slave_Monitor` ON
COMPLETION PRESERVE ENABLE;
通常情況下在PHP中MySQL查詢是串行的,如果能實(shí)現(xiàn)MySQL查詢的異步化,就能實(shí)現(xiàn)多條SQL語(yǔ)句同時(shí)執(zhí)行,這樣就能大大地縮短MySQL查詢的耗時(shí),提高數(shù)據(jù)庫(kù)查詢的效率。目前MySQL的異步查詢只在MySQLi擴(kuò)展提供,查詢方法分別是:
1、使用MYSQLI_ASYNC模式執(zhí)行mysqli::query
2、獲取異步查詢結(jié)果:mysqli::reap_async_query
使用mysql異步查詢,需要使用mysqlnd作為PHP的MySQL數(shù)據(jù)庫(kù)驅(qū)動(dòng)。
使用MySQL異步查詢,因?yàn)樾枰o所有查詢都創(chuàng)建一個(gè)新的連接,而MySQL服務(wù)端會(huì)為每個(gè)連接創(chuàng)建一個(gè)單獨(dú)的線程進(jìn)行處理,如果創(chuàng)建的線程過(guò)多,則會(huì)造成線程切換引起系統(tǒng)負(fù)載過(guò)高。Swoole中的異步MySQL其原理是通過(guò)MYSQLI_ASYNC模式查詢,然后獲取mysql連接的socket,加入到epoll事件循環(huán)中,當(dāng)數(shù)據(jù)庫(kù)返回結(jié)果時(shí)會(huì)回調(diào)指定函數(shù),這個(gè)過(guò)程是完全異步非阻塞的。
只要字段值還可以繼續(xù)拆分,就不滿足第一范式。
范式設(shè)計(jì)得越詳細(xì),對(duì)某些實(shí)際操作可能會(huì)更好,但并非都有好處,需要對(duì)項(xiàng)目的實(shí)際情況進(jìn)行設(shè)定。
在滿足第一范式的前提下,其他列都必須完全依賴(lài)于主鍵列。 如果出現(xiàn)不完全依賴(lài),只可能發(fā)生在聯(lián)合主鍵的情況下:
實(shí)際上,在這張訂單表中,product_name 只依賴(lài)于 product_id ,customer_name 只依賴(lài)于 customer_id。也就是說(shuō),product_name 和 customer_id 是沒(méi)用關(guān)系的,customer_name 和 product_id 也是沒(méi)有關(guān)系的。
這就不滿足第二范式:其他列都必須完全依賴(lài)于主鍵列!
拆分之后,myorder 表中的 product_id 和 customer_id 完全依賴(lài)于 order_id 主鍵,而 product 和 customer 表中的其他字段又完全依賴(lài)于主鍵。滿足了第二范式的設(shè)計(jì)!
在滿足第二范式的前提下,除了主鍵列之外,其他列之間不能有傳遞依賴(lài)關(guān)系。
表中的 customer_phone 有可能依賴(lài)于 order_id 、 customer_id 兩列,也就不滿足了第三范式的設(shè)計(jì):其他列之間不能有傳遞依賴(lài)關(guān)系。
修改后就不存在其他列之間的傳遞依賴(lài)關(guān)系,其他列都只依賴(lài)于主鍵列,滿足了第三范式的設(shè)計(jì)!
查詢每門(mén)課的平均成績(jī)。
查詢 score 表中至少有 2 名學(xué)生選修,并以 3 開(kāi)頭的課程的平均分?jǐn)?shù)。
分析表發(fā)現(xiàn),至少有 2 名學(xué)生選修的課程是 3-105 、3-245 、6-166 ,以 3 開(kāi)頭的課程是 3-105 、3-245。也就是說(shuō),我們要查詢所有 3-105 和 3-245 的 degree 平均分。
查詢所有學(xué)生的 name,以及該學(xué)生在 score 表中對(duì)應(yīng)的 c_no 和 degree 。
通過(guò)分析可以發(fā)現(xiàn),只要把 score 表中的 s_no 字段值替換成 student 表中對(duì)應(yīng)的 name 字段值就可以了,如何做呢?
查詢所有學(xué)生的 no 、課程名稱(chēng) ( course 表中的 name ) 和成績(jī) ( score 表中的 degree ) 列。
只有 score 關(guān)聯(lián)學(xué)生的 no ,因此只要查詢 score 表,就能找出所有和學(xué)生相關(guān)的 no 和 degree :
然后查詢 course 表:
只要把 score 表中的 c_no 替換成 course 表中對(duì)應(yīng)的 name 字段值就可以了。
查詢所有學(xué)生的 name 、課程名 ( course 表中的 name ) 和 degree 。
只有 score 表中關(guān)聯(lián)學(xué)生的學(xué)號(hào)和課堂號(hào),我們只要圍繞著 score 這張表查詢就好了。
只要把 s_no 和 c_no 替換成 student 和 srouse 表中對(duì)應(yīng)的 name 字段值就好了。
首先把 s_no 替換成 student 表中的 name 字段:
再把 c_no 替換成 course 表中的 name 字段:
查詢 95031 班學(xué)生每門(mén)課程的平均成績(jī)。
在 score 表中根據(jù) student 表的學(xué)生編號(hào)篩選出學(xué)生的課堂號(hào)和成績(jī):
這時(shí)只要將 c_no 分組一下就能得出 95031 班學(xué)生每門(mén)課的平均成績(jī):
查詢?cè)?3-105 課程中,所有成績(jī)高于 109 號(hào)同學(xué)的記錄。
首先篩選出課堂號(hào)為 3-105 ,在找出所有成績(jī)高于 109 號(hào)同學(xué)的的行。
查詢所有成績(jī)高于 109 號(hào)同學(xué)的 3-105 課程成績(jī)記錄。
查詢所有和 101 、108 號(hào)學(xué)生同年出生的 no 、name 、birthday 列。
查詢 '張旭' 教師任課的學(xué)生成績(jī)表。
首先找到教師編號(hào):
通過(guò) sourse 表找到該教師課程號(hào):
通過(guò)篩選出的課程號(hào)查詢成績(jī)表:
查詢某選修課程多于5個(gè)同學(xué)的教師姓名。
首先在 teacher 表中,根據(jù) no 字段來(lái)判斷該教師的同一門(mén)課程是否有至少5名學(xué)員選修:
查看和教師編號(hào)有有關(guān)的表的信息:
我們已經(jīng)找到和教師編號(hào)有關(guān)的字段就在 course 表中,但是還無(wú)法知道哪門(mén)課程至少有5名學(xué)生選修,所以還需要根據(jù) score 表來(lái)查詢:
根據(jù)篩選出來(lái)的課程號(hào),找出在某課程中,擁有至少5名學(xué)員的教師編號(hào):
在 teacher 表中,根據(jù)篩選出來(lái)的教師編號(hào)找到教師姓名:
查詢 “計(jì)算機(jī)系” 課程的成績(jī)表。
思路是,先找出 course 表中所有 計(jì)算機(jī)系 課程的編號(hào),然后根據(jù)這個(gè)編號(hào)查詢 score 表。
查詢 計(jì)算機(jī)系 與 電子工程系 中的不同職稱(chēng)的教師。
查詢課程 3-105 且成績(jī) 至少 高于 3-245 的 score 表。
查詢課程 3-105 且成績(jī)高于 3-245 的 score 表。
查詢某課程成績(jī)比該課程平均成績(jī)低的 score 表。
查詢所有任課 ( 在 course 表里有課程 ) 教師的 name 和 department 。
查詢 student 表中至少有 2 名男生的 class 。
查詢 student 表中不姓 "王" 的同學(xué)記錄。
查詢 student 表中每個(gè)學(xué)生的姓名和年齡。
查詢 student 表中最大和最小的 birthday 值。
以 class 和 birthday 從大到小的順序查詢 student 表。
查詢 "男" 教師及其所上的課程。
查詢最高分同學(xué)的 score 表。
查詢和 "李軍" 同性別的所有同學(xué) name 。
查詢和 "李軍" 同性別且同班的同學(xué) name 。
查詢所有選修 "計(jì)算機(jī)導(dǎo)論" 課程的 "男" 同學(xué)成績(jī)表。
需要的 "計(jì)算機(jī)導(dǎo)論" 和性別為 "男" 的編號(hào)可以在 course 和 student 表中找到。
建立一個(gè) grade 表代表學(xué)生的成績(jī)等級(jí),并插入數(shù)據(jù):
查詢所有學(xué)生的 s_no 、c_no 和 grade 列。
思路是,使用區(qū)間 ( BETWEEN ) 查詢,判斷學(xué)生的成績(jī) ( degree ) 在 grade 表的 low 和 upp 之間。
準(zhǔn)備用于測(cè)試連接查詢的數(shù)據(jù):
分析兩張表發(fā)現(xiàn),person 表并沒(méi)有為 cardId 字段設(shè)置一個(gè)在 card 表中對(duì)應(yīng)的 id 外鍵。如果設(shè)置了的話,person 中 cardId 字段值為 6 的行就插不進(jìn)去,因?yàn)樵?cardId 值在 card 表中并沒(méi)有。
要查詢這兩張表中有關(guān)系的數(shù)據(jù),可以使用 INNER JOIN ( 內(nèi)連接 ) 將它們連接在一起。
完整顯示左邊的表 ( person ) ,右邊的表如果符合條件就顯示,不符合則補(bǔ) NULL 。
完整顯示右邊的表 ( card ) ,左邊的表如果符合條件就顯示,不符合則補(bǔ) NULL 。
完整顯示兩張表的全部數(shù)據(jù)。
在 MySQL 中,事務(wù)其實(shí)是一個(gè)最小的不可分割的工作單元。事務(wù)能夠 保證一個(gè)業(yè)務(wù)的完整性 。
比如我們的銀行轉(zhuǎn)賬:
在實(shí)際項(xiàng)目中,假設(shè)只有一條 SQL 語(yǔ)句執(zhí)行成功,而另外一條執(zhí)行失敗了,就會(huì)出現(xiàn)數(shù)據(jù)前后不一致。
因此,在執(zhí)行多條有關(guān)聯(lián) SQL 語(yǔ)句時(shí), 事務(wù) 可能會(huì)要求這些 SQL 語(yǔ)句要么同時(shí)執(zhí)行成功,要么就都執(zhí)行失敗。
在 MySQL 中,事務(wù)的 自動(dòng)提交 狀態(tài)默認(rèn)是開(kāi)啟的。
自動(dòng)提交的作用 :當(dāng)我們執(zhí)行一條 SQL 語(yǔ)句的時(shí)候,其產(chǎn)生的效果就會(huì)立即體現(xiàn)出來(lái),且不能 回滾 。
什么是回滾?舉個(gè)例子:
可以看到,在執(zhí)行插入語(yǔ)句后數(shù)據(jù)立刻生效,原因是 MySQL 中的事務(wù)自動(dòng)將它 提交 到了數(shù)據(jù)庫(kù)中。那么所謂 回滾 的意思就是,撤銷(xiāo)執(zhí)行過(guò)的所有 SQL 語(yǔ)句,使其回滾到 最后一次提交 數(shù)據(jù)時(shí)的狀態(tài)。
在 MySQL 中使用 ROLLBACK 執(zhí)行回滾:
由于所有執(zhí)行過(guò)的 SQL 語(yǔ)句都已經(jīng)被提交過(guò)了,所以數(shù)據(jù)并沒(méi)有發(fā)生回滾。那如何讓數(shù)據(jù)可以發(fā)生回滾?
將自動(dòng)提交關(guān)閉后,測(cè)試數(shù)據(jù)回滾:
那如何將虛擬的數(shù)據(jù)真正提交到數(shù)據(jù)庫(kù)中?使用 COMMIT :
事務(wù)的實(shí)際應(yīng)用 ,讓我們?cè)倩氐姐y行轉(zhuǎn)賬項(xiàng)目:
這時(shí)假設(shè)在轉(zhuǎn)賬時(shí)發(fā)生了意外,就可以使用 ROLLBACK 回滾到最后一次提交的狀態(tài):
這時(shí)我們又回到了發(fā)生意外之前的狀態(tài),也就是說(shuō),事務(wù)給我們提供了一個(gè)可以反悔的機(jī)會(huì)。假設(shè)數(shù)據(jù)沒(méi)有發(fā)生意外,這時(shí)可以手動(dòng)將數(shù)據(jù)真正提交到數(shù)據(jù)表中:COMMIT 。
事務(wù)的默認(rèn)提交被開(kāi)啟 ( @@AUTOCOMMIT = 1 ) 后,此時(shí)就不能使用事務(wù)回滾了。但是我們還可以手動(dòng)開(kāi)啟一個(gè)事務(wù)處理事件,使其可以發(fā)生回滾:
仍然使用 COMMIT 提交數(shù)據(jù),提交后無(wú)法再發(fā)生本次事務(wù)的回滾。
事務(wù)的四大特征:
事務(wù)的隔離性可分為四種 ( 性能從低到高 ) :
查看當(dāng)前數(shù)據(jù)庫(kù)的默認(rèn)隔離級(jí)別:
修改隔離級(jí)別:
測(cè)試 READ UNCOMMITTED ( 讀取未提交 ) 的隔離性:
由于小明的轉(zhuǎn)賬是在新開(kāi)啟的事務(wù)上進(jìn)行操作的,而該操作的結(jié)果是可以被其他事務(wù)(另一方的淘寶店)看見(jiàn)的,因此淘寶店的查詢結(jié)果是正確的,淘寶店確認(rèn)到賬。但就在這時(shí),如果小明在它所處的事務(wù)上又執(zhí)行了 ROLLBACK 命令,會(huì)發(fā)生什么?
這就是所謂的 臟讀 ,一個(gè)事務(wù)讀取到另外一個(gè)事務(wù)還未提交的數(shù)據(jù)。這在實(shí)際開(kāi)發(fā)中是不允許出現(xiàn)的。
把隔離級(jí)別設(shè)置為 READ COMMITTED :
這樣,再有新的事務(wù)連接進(jìn)來(lái)時(shí),它們就只能查詢到已經(jīng)提交過(guò)的事務(wù)數(shù)據(jù)了。但是對(duì)于當(dāng)前事務(wù)來(lái)說(shuō),它們看到的還是未提交的數(shù)據(jù),例如:
但是這樣還有問(wèn)題,那就是假設(shè)一個(gè)事務(wù)在操作數(shù)據(jù)時(shí),其他事務(wù)干擾了這個(gè)事務(wù)的數(shù)據(jù)。例如:
雖然 READ COMMITTED 讓我們只能讀取到其他事務(wù)已經(jīng)提交的數(shù)據(jù),但還是會(huì)出現(xiàn)問(wèn)題,就是 在讀取同一個(gè)表的數(shù)據(jù)時(shí),可能會(huì)發(fā)生前后不一致的情況。* 這被稱(chēng)為* 不可重復(fù)讀現(xiàn)象 ( READ COMMITTED ) 。
將隔離級(jí)別設(shè)置為 REPEATABLE READ ( 可被重復(fù)讀取 ) :
測(cè)試 REPEATABLE READ ,假設(shè)在兩個(gè)不同的連接上分別執(zhí)行 START TRANSACTION :
當(dāng)前事務(wù)開(kāi)啟后,沒(méi)提交之前,查詢不到,提交后可以被查詢到。但是,在提交之前其他事務(wù)被開(kāi)啟了,那么在這條事務(wù)線上,就不會(huì)查詢到當(dāng)前有操作事務(wù)的連接。相當(dāng)于開(kāi)辟出一條單獨(dú)的線程。
無(wú)論小張是否執(zhí)行過(guò) COMMIT ,在小王這邊,都不會(huì)查詢到小張的事務(wù)記錄,而是只會(huì)查詢到自己所處事務(wù)的記錄:
這是 因?yàn)樾⊥踉诖酥伴_(kāi)啟了一個(gè)新的事務(wù) ( START TRANSACTION ) * ,那么* 在他的這條新事務(wù)的線上,跟其他事務(wù)是沒(méi)有聯(lián)系的 ,也就是說(shuō),此時(shí)如果其他事務(wù)正在操作數(shù)據(jù),它是不知道的。
然而事實(shí)是,在真實(shí)的數(shù)據(jù)表中,小張已經(jīng)插入了一條數(shù)據(jù)。但是小王此時(shí)并不知道,也插入了同一條數(shù)據(jù),會(huì)發(fā)生什么呢?
報(bào)錯(cuò)了,操作被告知已存在主鍵為 6 的字段。這種現(xiàn)象也被稱(chēng)為 幻讀,一個(gè)事務(wù)提交的數(shù)據(jù),不能被其他事務(wù)讀取到 。
顧名思義,就是所有事務(wù)的 寫(xiě)入操作 全都是串行化的。什么意思?把隔離級(jí)別修改成 SERIALIZABLE :
還是拿小張和小王來(lái)舉例:
此時(shí)會(huì)發(fā)生什么呢?由于現(xiàn)在的隔離級(jí)別是 SERIALIZABLE ( 串行化 ) ,串行化的意思就是:假設(shè)把所有的事務(wù)都放在一個(gè)串行的隊(duì)列中,那么所有的事務(wù)都會(huì)按照 固定順序執(zhí)行 ,執(zhí)行完一個(gè)事務(wù)后再繼續(xù)執(zhí)行下一個(gè)事務(wù)的 寫(xiě)入操作 ( 這意味著隊(duì)列中同時(shí)只能執(zhí)行一個(gè)事務(wù)的寫(xiě)入操作 ) 。
根據(jù)這個(gè)解釋?zhuān)⊥踉诓迦霐?shù)據(jù)時(shí),會(huì)出現(xiàn)等待狀態(tài),直到小張執(zhí)行 COMMIT 結(jié)束它所處的事務(wù),或者出現(xiàn)等待超時(shí)。
轉(zhuǎn)載:
1、命令查看是否開(kāi)啟event_scheduleSHOWVARIABLESLIKE'event_scheduler'。
2、使用命令開(kāi)啟臨時(shí)開(kāi)啟,重啟mysql又還原回去。
3、修改配置永久修改配置文件的[mysqld]部分加上event_scheduler=ON。
分享名稱(chēng):mysql事件怎么處理 mysql的事務(wù)是怎么實(shí)現(xiàn)的
鏈接分享:http://jinyejixie.com/article24/hepije.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化、小程序開(kāi)發(fā)、Google、自適應(yīng)網(wǎng)站、建站公司、網(wǎng)站排名
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)