剛剛寫完事務控制原理的理解,趁熱打鐵,順便也把隔離級別說說。主要就是給演示一下jdbc的髒讀(其他的隔離級別就不實現了,順着這個思路自行實驗吧,主要通過這個實驗給你更加直觀的體驗)。
隔離級別的概念也算數據庫操作中比較有名的了吧,以前也常聽人說起,但是一直未曾見其真身,一提起這個名詞總感覺暈暈乎乎的,似乎知道,但又不知道,今天成有機會,來自行實現一把,看看他的真身,也加深自己的理解。
準備的原材料
一張簡單的表,就一條數據,但是夠了。
隔離節別表,這裏偷個懶,截上圖放這把。
至於這些級別的更詳細的解釋,這裏就不介紹了,推薦大家看這篇博文,講的很好。
mysql tx_isolation
這些隔離級別在MySQL數據庫中的查看方式如下:
select @@transaction_isolation; //我用的是8版本的數據庫
select @@tx_isolation; //低版本的
設置MySQL的隔離級別
set transaction_isolation = ‘read-uncommitted’; //支持髒讀
select @@transaction_isolation;
更改設置之後的隔離級別
代碼如下
在update
操作commit
之前讀取數據。
public static void main(String[] args) throws ClassNotFoundException, SQLException, InterruptedException {
Connection conn = null;
Statement statement = null;
//1、註冊驅動
//本地安裝的數據庫版本要和驅動版本對應,否則報錯無法創建連接
Class.forName("com.mysql.cj.jdbc.Driver");
//2、獲取連接
conn = DriverManager.getConnection(url, dbName, dbPass);
conn.setAutoCommit(false); //關閉自動提交
//3、獲取一個statement
statement = conn.createStatement();
//4、執行更新的sql語句
String sqlUpdate = "update account set money=0 where name='張三'";
statement.execute(sqlUpdate);
//5、執行查詢sql語句,查詢未提交的數據
//髒讀產生點
String sqlQuery = "select * from account where name='張三'";
ResultSet resultSet = statement.executeQuery(sqlQuery);
while (resultSet.next()){
System.out.println(resultSet.getInt("money"));
}
conn.commit();
//5、關閉statement和connection
if (statement!=null){
statement.close();
}
if (conn!=null){
conn.close();
}
結果是什麼你們想一下,0?
1000,WTK?
我明明在MySQL中修改成了read uncommitted(未提交讀)
呀。
但是不應該在MySQL中設置,而應該在jdbc代碼中設置(其實我很不理解,我的底層都支持了,你一個調用我的,竟然敢違揹我。是在不解這是怎麼回事,還望路過的大佬不吝賜教)。
下面我們的看一下connection的一些我們平時用的比較少的功能。
//獲得jdbc的connection的隔離級別,我是第一次用,原諒我是個菜鳥
int isolation = conn.getTransactionIsolation();
System.out.println("isolation = " + isolation);
不應該上面說的那些嗎,怎麼出來一個整數呢。原來這羣人又在完幺蛾子
可以看到我們現在的級別根本就不支持髒讀,所以還需要設置一下隔離級別
//2、獲取連接
conn = DriverManager.getConnection(url, dbName, dbPass);
conn.setAutoCommit(false); //關閉自動提交
conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
這回就對了嘛。
所以說在spring的配置中,我們纔可以在代碼中配置事務的隔離級別,而不是去修改物理的MySQL的隔離級別。