MySQL 事務(wù)
成都創(chuàng)新互聯(lián)主要為客戶提供服務(wù)項目涵蓋了網(wǎng)頁視覺設(shè)計、VI標志設(shè)計、營銷型網(wǎng)站建設(shè)、網(wǎng)站程序開發(fā)、HTML5響應(yīng)式成都網(wǎng)站建設(shè)、手機網(wǎng)站制作、微商城、網(wǎng)站托管及成都網(wǎng)站維護、WEB系統(tǒng)開發(fā)、域名注冊、國內(nèi)外服務(wù)器租用、視頻、平面設(shè)計、SEO優(yōu)化排名。設(shè)計、前端、后端三個建站步驟的完善服務(wù)體系。一人跟蹤測試的建站服務(wù)標準。已經(jīng)為衛(wèi)生間隔斷行業(yè)客戶提供了網(wǎng)站營銷服務(wù)。
什么是事務(wù)?
MySQL 事務(wù)主要用于處理操作量大,復雜度高的數(shù)據(jù)。比如說,在人員管理系統(tǒng)中,你刪除一個人員,你既需要刪除人員的基本資料,也要刪除和該人員相關(guān)的信息,如信箱,文章等等,這樣,這些數(shù)據(jù)庫操作語句就構(gòu)成一個事務(wù)!
在 MySQL 中只有使用了 Innodb 數(shù)據(jù)庫引擎的數(shù)據(jù)庫或表才支持事務(wù)。
事務(wù)處理可以用來維護數(shù)據(jù)庫的完整性,保證成批的 SQL 語句要么全部執(zhí)行,要么全部不執(zhí)行。
事務(wù)用來管理 insert,update,delete 語句
一般來說,事務(wù)是必須滿足4個條件(ACID):原子性(Atomicity,或稱不可分割性)、一致性(Consistency)、隔離性(Isolation,又稱獨立性)、持久性(Durability)。
原子性:一個事務(wù)(transaction)中的所有操作,要么全部完成,要么全部不完成,不會結(jié)束在中間某個環(huán)節(jié)。事務(wù)在執(zhí)行過程中發(fā)生錯誤,會被回滾(Rollback)到事務(wù)開始前的狀態(tài),就像這個事務(wù)從來沒有執(zhí)行過一樣。
一致性:在事務(wù)開始之前和事務(wù)結(jié)束以后,數(shù)據(jù)庫的完整性沒有被破壞。這表示寫入的資料必須完全符合所有的預(yù)設(shè)規(guī)則,這包含資料的精確度、串聯(lián)性以及后續(xù)數(shù)據(jù)庫可以自發(fā)性地完成預(yù)定的工作。
隔離性:數(shù)據(jù)庫允許多個并發(fā)事務(wù)同時對其數(shù)據(jù)進行讀寫和修改的能力,隔離性可以防止多個事務(wù)并發(fā)執(zhí)行時由于交叉執(zhí)行而導致數(shù)據(jù)的不一致。事務(wù)隔離分為不同級別,包括讀未提交(Read uncommitted)、讀提交(read committed)、可重復讀(repeatable read)和串行化(Serializable)。
持久性:事務(wù)處理結(jié)束后,對數(shù)據(jù)的修改就是永久的,即便系統(tǒng)故障也不會丟失。
在 MySQL 命令行的默認設(shè)置下,事務(wù)都是自動提交的,即執(zhí)行 SQL 語句后就會馬上執(zhí)行 COMMIT 操作。因此要顯式地開啟一個事務(wù)務(wù)須使用命令 BEGIN 或 START TRANSACTION,或者執(zhí)行命令 SET AUTOCOMMIT=0,用來禁止使用當前會話的自動提交。
from 樹懶學堂 - 一站式數(shù)據(jù)知識平臺
1.一條查詢語句如何執(zhí)行?
2.一條更新語句如何執(zhí)行?
3.innodb的redolog是什么?
4.什么是寫緩沖
5.寫緩沖一定好嗎?
6.什么情況會引發(fā)刷臟頁
關(guān)于一條mysql查詢語句在mysql中的執(zhí)行流程
如select name from test where id=10;
1.連接器---先與mysql服務(wù)端連接器建立連接,若查詢緩存命中則直接返回 (查詢緩存的弊端:查詢緩存的失效非常頻繁,只要有對一個表的更新,這個表上所有的查詢緩存都會被清空。)
2.分析器---詞法分析告訴服務(wù)端你要干什么(我要找 test表中id為10的名字) ( 其中sql語法錯誤在這塊暴露 )
3.優(yōu)化器---服務(wù)端會思考該怎么執(zhí)行最優(yōu)(索引的選擇)
4.執(zhí)行器---檢查用戶對庫對表的權(quán)限
5.存儲引擎--存儲數(shù)據(jù),提供讀寫接口
以update a set name=1 where id=1;
主要區(qū)別在于在查詢到數(shù)據(jù)之后(select name from a where id=1),如果是innodb引擎它會進行日志的兩階段提交:
1.開啟事務(wù),寫入redolog(innodb引擎特有),并更新內(nèi)存
3.寫入binlog,提交事務(wù),commit
我們知道m(xù)ysql數(shù)據(jù)存儲包含內(nèi)存與磁盤兩個部分,innodb是按數(shù)據(jù)頁(通常為16k)從磁盤讀取到內(nèi)存中的(剩余操作在內(nèi)存中執(zhí)行),當要更新數(shù)據(jù)時,若目標數(shù)據(jù)的數(shù)據(jù)頁剛好在內(nèi)存中,則直接更新。不在呢?
將這個更新操作(也可能是插入) 緩存在change buffer中 (redolog也會記錄這個change buffer操作)等到下一次查詢要用到這些數(shù)據(jù)時,再執(zhí)行這些操作,改變數(shù)據(jù)(稱為合并操作記錄稱為merge)。
innodb_change_buffer_max_size
innodb_change_buffering
先介紹兩個概念
因為redolog是環(huán)形日志,當redolog寫滿時,就需要“擦掉”開頭的一部分數(shù)據(jù)來達到循環(huán)寫,這里的擦掉指,指將redolog日志的checkpoint位置從 CP推進到CP‘ ,同時將兩點之間的臟頁刷到磁盤上(flush操作),此時系統(tǒng)要停止所有的更新操作(防止更新操作丟失)
1.系統(tǒng)內(nèi)存不足。當要讀取新的內(nèi)存頁時就要淘汰一些數(shù)據(jù)頁,如果淘汰的正好是臟頁,就要執(zhí)行一次flush操作
2.Mysql認為系統(tǒng)處于“空閑狀態(tài)”
3.正常關(guān)閉Mysql
上述后兩者場景(系統(tǒng)空閑和正常關(guān)閉)對于性能都沒太大影響。
當為第一種redolog寫滿時,系統(tǒng)無法執(zhí)行更新操作,所有操作都會堵塞
當為第二種內(nèi)存不夠用時,如果淘汰臟頁太多,影響mysql響應(yīng)時間
后兩者刷臟頁會影響性能,所以Mysql需要有刷臟頁控制策略,可以從以下幾個設(shè)置項考慮
1.設(shè)置innodb_io_capacity告訴innodb所在主機的IO能力
MySQL是一個關(guān)系型數(shù)據(jù)庫管理系統(tǒng),由瑞典MySQL AB公司開發(fā),屬于Oracle旗下產(chǎn)品,是最流行的關(guān)系型數(shù)據(jù)庫管理系統(tǒng)之一。
端口是3306。
表很多時,使用linux腳本,需要根據(jù)需要修改一下:
和創(chuàng)建一樣,可以加上 if exists
可兩篇文章:
如:
用于在已有的表中添加、刪除或修改列。
添加 ADD
或
默認是添加到最后,但可以指定位置。 FIRST :添加最前
AFTER 字段名 :添加指定字段之后
例子:
刪除 DROP
修改 MODIFY 主要修改原列的類型或約束條件 同樣可以用 FIRST 和 AFTER 字段名 ,代表的是修改到哪里。
修改字段名 CHANGE
可以把表2的數(shù)據(jù)復制到表1中,但 不能復制約束性條件 。
單行
多行,注意 只有一個VALUES :
不寫 (行1, 行2...) 這一部分的話,默認一一對應(yīng)
除了以上方法外,還可以用SET為每一行附上相應(yīng)的值。
假如沒有篩選的話,就給全部都修改了。可以用 WHERE 篩選。
假如 沒有篩選的話,就給全部刪除了 。相當于清空。
清空
先把表刪除,然后再建一個。與 DELETE FROM 相比, TRUNCATE 的效率更快,因為 DELETE FROM 是把記錄逐條刪除的。
查詢執(zhí)行的順序
FROM -- WHERE -- SELECT -- GROUP BY -- HAVING -- ORDER BY -- LIMIT
注意
當數(shù)據(jù)很大,上百萬的時候,使用LIMIT ... OFFSET ..的方式進行分頁十分浪費資源且耗時長。最好是結(jié)合WHERE使用,如:
REGEXP 使用正則表達進行匹配。 查詢時,需要搭配WHERE或HAVING使用 。
兩個表之間有交集且要用到兩個表的數(shù)據(jù)時,可以使用內(nèi)連接查詢。
LEFT JOIN 關(guān)鍵字從左表(table1)返回所有的行,即使右表(table2)中沒有匹配。如果右表中沒有匹配,則結(jié)果為 NULL。
用法:
RIGHT JOIN 關(guān)鍵字從右表(table2)返回所有的行,即使左表(table1)中沒有匹配。如果左表中沒有匹配,則結(jié)果為 NULL。 把LEFT JOIN的表1、表2調(diào)換順序,就是REGHT JOIN 。
FULL OUTER JOIN 關(guān)鍵字只要左表(table1)和右表(table2)其中一個表中存在匹配,則返回行. 相當于結(jié)合了 LEFT JOIN 和 RIGHT JOIN 的結(jié)果。
但 MySQL中不支持 FULL OUTER JOIN 。
即SELECT嵌套。
IN 一個查詢結(jié)果作為另一個查詢的條件。 如:
EXISTS 用于判斷查詢子句是否有記錄,如果有一條或多條記錄存在返回 True,否則返回 False。True時執(zhí)行。 如:
索引的本質(zhì)是一種排好序的數(shù)據(jù)結(jié)構(gòu)。利用索引可以提高查詢速度。
常見的索引有:
MySQL通過外鍵約束來保證表與表之間的數(shù)據(jù)的完整性和準確性。 外鍵的使用條件:
外鍵的好處:可以使得兩張表關(guān)聯(lián),保證數(shù)據(jù)的一致性和實現(xiàn)一些級聯(lián)操作。
對已有的兩個表增加外鍵 比如:主表為A,子表為B,外鍵為aid,外鍵約束名字為a_fk_b
為子表添加一個字段,當做外鍵
為子表添加外鍵約束條件
假如刪除記錄報錯: [Err] 1451 -Cannot deleteorupdatea parent row: aforeignkeyconstraintfails (...)
這是因為MySQL中設(shè)置了foreign key關(guān)聯(lián),造成無法更新或刪除數(shù)據(jù)??梢酝ㄟ^設(shè)置 FOREIGN_KEY_CHECKS 變量來避免這種情況。 第一步:禁用外鍵約束,我們可以使用: SETFOREIGN_KEY_CHECKS=0; 第二步:刪除數(shù)據(jù) 第三步:啟動外鍵約束,我們可以使用: SETFOREIGN_KEY_CHECKS=1; 查看當前FOREIGN_KEY_CHECKS的值,可用如下命令: SELECT @@FOREIGN_KEY_CHECKS;
使用 UNION 來組合兩個查詢,如果第一個查詢返回 M 行,第二個查詢返回 N 行,那么組合查詢的結(jié)果一般為 M+N 行。
每個查詢必須包含相同的列、表達式和聚集函數(shù)。
默認會去除相同行,如果需要 保留 相同行,使用 UNION ALL 。
只能包含一個 ORDER BY 子句,并且必須位于語句的最后 。
內(nèi)置函數(shù)很多, 見: MySQL 函數(shù)
我們一般使用 START TRANSACTION 或 BEGIN 開啟事務(wù), COMMIT 提交事務(wù)中的命令, SAVEPOINT : 相當于設(shè)置一個還原點, ROLLBACK TO : 回滾到某個還原點下
一般的使用格式如下:
開啟事務(wù)時, 默認加鎖
根據(jù)類型可分為共享鎖(SHARED LOCK)和排他鎖(EXCLUSIVE LOCK)或者叫讀鎖(READ LOCK)和寫鎖(WRITE LOCK)。
根據(jù)粒度劃分又分表鎖和行鎖。表鎖由數(shù)據(jù)庫服務(wù)器實現(xiàn),行鎖由存儲引擎實現(xiàn)。
除此之外,我們可以顯示加鎖
加鎖時, 如果沒有索引,會鎖表,如果加了索引,就會鎖行
InnoDB默認支持行鎖,獲取鎖是分步的,并不是一次性獲取所有的鎖,因此在鎖競爭的時候就會出現(xiàn)死鎖的情況
解決方法:
即ACID特性:
由于并發(fā)事務(wù)會引發(fā)上面這些問題, 我們可以設(shè)置事務(wù)的隔離級別解決上面的問題.
MySQL的默認隔離級別(可重復讀)
查看當前會話隔離級別
方式1
方式2
設(shè)置隔離級別
主從集群的示意圖如下:
主要涉及三個線程: binlog 線程、 I/O 線程和 SQL 線程。
同步流程:
由于MySQL主從集群只會從主節(jié)點同步到從節(jié)點, 不會反過來同步, 所以需要讀寫分離
讀寫分離需要在業(yè)務(wù)層面實現(xiàn) , 寫數(shù)據(jù)只能在主節(jié)點上完成, 而讀數(shù)據(jù)可以在主節(jié)點或從節(jié)點上完成
索引是幫助MySQL高效獲取數(shù)據(jù)的排好序的數(shù)據(jù)結(jié)構(gòu)
MySQL的索引有
推薦兩個在線工具:
簡單來說, B樹是在紅黑樹(一個平衡二叉樹)的基礎(chǔ)上將一個節(jié)點存放多個值, 實現(xiàn)的, 降低了樹的高度, 每個節(jié)點都存放索引及對應(yīng)數(shù)據(jù)指針, 同一層的節(jié)點是遞增的
而B+樹在B樹的基礎(chǔ)上進行優(yōu)化, 非葉子節(jié)點存放 子節(jié)點的開始的索引, 葉子節(jié)點存放索引和數(shù)據(jù)的指針, 且葉子節(jié)點之間有雙向的指針
如下示意圖:
不同的引擎, 主鍵索引存放的數(shù)據(jù)也不一樣, 比如常見的 MyISAM 和 InnoDB
MyISAM 的B+樹葉子節(jié)點存放表數(shù)據(jù)的指針, InnoDB 的B+樹葉子節(jié)點存放處主鍵外的數(shù)據(jù)
其他的:
即多個列組成一個索引, 語法:
由于聯(lián)合索引的B+樹的結(jié)構(gòu), 根據(jù)列建立, 所以我們的查找條件也要根據(jù)索引列的順序( where column1=x, column2=y,columnN... ), 否則會全表掃描
如果你對列進行了 (+,-,*,/,!) , 那么都將不會走索引。
OR 引起的索引失效
OR 導致索引是在特定情況下的,并不是所有的 OR 都是使索引失效,如果OR連接的是 同 一個字段,那么索引 不會失效 , 反之索引失效 。
這個我相信大家都明白,模糊搜索如果你前綴也進行模糊搜索,那么不會走索引。
這兩種用法,也將使索引失效。另 IN 會走索引,但是當IN的取值范圍較大時會導致索引失效,走全表掃描, 見: MySQL中使用IN會不會走索引
不走索引。
走索引。
所以設(shè)計表的時候, 建議不可為空, 而是將默認值設(shè)置為 "" ( NOT NULL DEFAULT "" )
看你是什么事務(wù),jdbc事務(wù),還是分布式事務(wù),還是容器事務(wù)
1,編程式事務(wù)管理(jdbc的事務(wù)是綁定在connection上的)
Connection conn = null;
try
{
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:oracle:thin:@host:1521:SID","username","password");
conn.setAutoCommit(false); //取消自動提交
PreparedStatement ps = conn.prepareCall("update something");
ResultSet rs = ps.executeQuery();
conn.commit(); //手動提交
}
catch (Exception e)
{
conn.rollback();
e.printStackTrace();
}
finally
{
conn.close();
}
2,聲明式事務(wù)
先在工程的application.xml配置文件中添加如下代碼,開啟事務(wù)
!-- 聲明式事務(wù)控制配置 --
tx:annotation-driven transaction-manager="txManager"/
bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
property name="datasource" ref="bassDataSource"/property
/bean
然后在你需要開啟事務(wù)的接口前面添加注解
@Transactional(rollbackFor = IOException.class)
public void add(String name) throws IOException
{
System.out.println("可以再類里和方法里面添加事務(wù)注解0~0");
throw new IOException();
}
直接調(diào)用接口方法就好
分布式事務(wù)處理(mysql貌似在5.X之后才支持) 的話,
1.可以直接使用spring+atomikos框架進行管理
參考:
就不貼測試代碼了,自己看著配置吧
2,使用JTA(Java Transaction API)進行分布式事務(wù)管理(測試代碼如下)
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import javax.transaction.SystemException;
import javax.transaction.UserTransaction;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
//分布式事務(wù)處理
public class transferAccount
{
@SuppressWarnings("null")
public void testTransferAccount()
{
UserTransaction userts = null;
Connection connA = null;
PreparedStatement psA = null;
InitialContext context = null;
Connection connB = null;
PreparedStatement psB = null;
try
{
//獲得事務(wù)管理對象
userts = (UserTransaction) context.lookup("java:comp/UserTransaction");
//獲取兩個數(shù)據(jù)庫
connA = getDataSourceA().getConnection();
connB = getDataSourceB().getConnection();
//開啟事務(wù)
userts.begin();
//sql語句
psA = connA.prepareStatement("我加1");
psB = connB.prepareStatement("我減1");
//執(zhí)行sql
psA.executeUpdate();
psB.executeUpdate();
//事務(wù)提交
userts.commit();
} catch (Exception e)
{
try
{
userts.rollback();
} catch (IllegalStateException | SecurityException
| SystemException e1)
{
e1.printStackTrace();
}
e.printStackTrace();
}
finally
{
try
{
psA.close();
psB.close();
connA.close();
connB.close();
} catch (SQLException e)
{
e.printStackTrace();
}
}
}
public DataSource getDataSourceA()
{
MysqlDataSource dataSource = new MysqlDataSource();
dataSource.setDatabaseName("mysql");
dataSource.setServerName("server");
dataSource.setPortNumber(1433);
dataSource.setUser("test");
dataSource.setPassword("test");
return dataSource;
}
public DataSource getDataSourceB()
{
MysqlDataSource dataSource = new MysqlDataSource();
dataSource.setDatabaseName("mysql");
dataSource.setServerName("server");
dataSource.setPortNumber(1435);
dataSource.setUser("test1");
dataSource.setPassword("test1");
return dataSource;
}
}
網(wǎng)站名稱:mysql怎么開啟事務(wù),mysql查詢需要開啟事務(wù)嗎
當前鏈接:http://jinyejixie.com/article42/hsiohc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App開發(fā)、小程序開發(fā)、手機網(wǎng)站建設(shè)、搜索引擎優(yōu)化、移動網(wǎng)站建設(shè)、用戶體驗
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)