3.mysql事務(wù)
事務(wù)sql相關(guān)語法
-- 1.查看當(dāng)前表的存儲引擎
show create table te ;
show variables like '%storage_engine%';
-- 2.開啟事務(wù)、事務(wù)回滾换衬、事務(wù)提交痰驱、還原點(diǎn)
begin/rollback/commit/savepoint
show variables like '%autocommit%'
-- 關(guān)閉自動提交
set autocommit = 0;
insert into te values(3,3);
savepoint n1;
insert into te values(4,4);
savepoint n2;
insert into te values(5,5);
rollback to savepoint n1;
select * from te
關(guān)閉事務(wù)自動提交,插入3,set n1,插入4,set n2,插入5 查詢?nèi)龡l已插入瞳浦,執(zhí)行rollback n1担映,查詢有一條數(shù)據(jù)
插入
1) 特性ACID
1.原子性:一個(gè)事務(wù)是不可分割的工作單位,一批操作要么成功要么失敗
例,a轉(zhuǎn)b100元叫潦,a賬號減100蝇完,b賬號就增加100;
2.一致性:從一個(gè)一致性狀態(tài)變到另一個(gè)一致性狀態(tài),
例,a轉(zhuǎn)b100元,a賬號減100短蜕,b賬號就增加100,增加和扣減的符合氢架,這就是一直性
3.隔離性:一個(gè)事務(wù)執(zhí)行不能被其它事務(wù)干擾,
4.持久性:一個(gè)事務(wù)一旦提交朋魔,它對數(shù)據(jù)庫中的數(shù)據(jù)改變就應(yīng)該是永久性
例,事務(wù)提交了岖研,數(shù)據(jù)就會被持久到磁盤中
隔離性
1.未提交讀(臟讀) read uncommitted
事務(wù)a讀取了事務(wù)b更新的數(shù)據(jù),然后b回滾警检,那么a讀取到就是臟數(shù)據(jù)
CREATE TABLE `te` (
`id` int(11) NOT NULL,
`score` int(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf16 COLLATE=utf16_bin
insert into te values(1,100);
原數(shù)據(jù)
id score
1 100
事務(wù)a
-- 1. 設(shè)置未提交讀
set session transaction isolation level read uncommitted;
-- 2.開啟事務(wù)
begin
update te set score = score -1 where id = 1;
select * from te where id = 1;
-- 3.事務(wù)回滾
ROLLBACK
事務(wù)b
-- 1. 設(shè)置未提交讀
set session transaction isolation level read uncommitted;
-- 2.開啟事務(wù)
begin
-- 3.查詢
select * from te where id = 1;
先執(zhí)行a1 a2 然后執(zhí)行b1 b2 執(zhí)行a-update操作孙援,然后執(zhí)行b3,結(jié)果為99扇雕,然后a3回滾事務(wù)拓售,b3讀取的就是臟數(shù)據(jù)
2.已提提交讀(不可重復(fù)讀)-read commited
事務(wù)a多次讀取同一條數(shù)據(jù),事務(wù)b修改了數(shù)據(jù)并提交镶奉,導(dǎo)致事務(wù)a讀取到的數(shù)據(jù)前后不一致
事務(wù)a
-- 1. 設(shè)置已提提交讀(不可重復(fù)讀)
set session transaction isolation level read committed;
-- 2.開啟事務(wù)
begin
update te set score = score -1 where id = 1;
-- 3.查詢
select * from te where id = 1;
-- 4.事務(wù)回滾
ROLLBACK
事務(wù)b
-- 1. 設(shè)置已提提交讀(不可重復(fù)讀)
set session transaction isolation level read committed;
-- 2.開啟事務(wù)
begin
-- 3.查詢
select * from te where id = 1;
commit
先執(zhí)行a1 a2 然后執(zhí)行b1 b2 執(zhí)行a-update操作础淤,執(zhí)行a3為結(jié)果查詢?yōu)?9,而b3查詢結(jié)果還是100
但是事務(wù)a提交了哨苛,b3查詢則為99值骇,這就是跟可重復(fù)讀區(qū)別
3.可重復(fù)讀-repeatable read
事務(wù)a開啟,事務(wù)b開啟移国,事務(wù)a修改后,提交事務(wù)道伟,事務(wù)b查詢時(shí)修改前的數(shù)據(jù)
事務(wù)a
-- 1.設(shè)置已提提交讀(不可重復(fù)讀)
set session transaction isolation level repeatable read;
-- 2.開啟事務(wù)
begin
update te set score = score -1 where id = 1;
-- 3.查詢
select * from te where id = 1;
-- 4.事務(wù)回滾
ROLLBACK
commit
事務(wù)b
-- 1. 設(shè)置已提提交讀(不可重復(fù)讀)
set session transaction isolation level repeatable read;
-- 2.開啟事務(wù)
begin;
-- 3.查詢
select * from te where id = 1;
commit
先執(zhí)行a1 a2 然后執(zhí)行b1 b2,然后執(zhí)行a-update迹缀,查詢a3結(jié)果為99,查詢b3結(jié)果為100蜜徽,然后事務(wù)commit祝懂,
繼續(xù)查詢b3結(jié)果還是100,然后b3commit拘鞋,重新執(zhí)行b3砚蓬,結(jié)果則變成99
4.可串行讀-serializable
幻讀:事務(wù)a開啟,將表中所有數(shù)據(jù)修改成1盆色,同時(shí)事務(wù)b插入一條值為2的數(shù)據(jù)灰蛙,a就會發(fā)現(xiàn)自己并未完全修改好,
sql就不來演示了
總結(jié)
- 1.事務(wù)隔離級別為可重復(fù)讀隔躲,如果有索引的時(shí)候摩梧,已索引為條件更新數(shù)據(jù),會存在行鎖宣旱、頁鎖仅父、間隙鎖的問題,如果沒有索引,更新數(shù)據(jù)時(shí)會鎖住整張表(行鎖升級為表鎖);
- 2.隔離級別越高笙纤,越能保證事務(wù)的一致性耗溜,并發(fā)性能就較低,根據(jù)自己應(yīng)用省容,合理選擇事務(wù)的隔離級別;
- 3.不可重復(fù)讀側(cè)重于修改抖拴,幻讀側(cè)重于新增和刪除,解決不可重復(fù)讀鎖行蓉冈,而幻讀則要鎖表;
- 4.事務(wù)級別為串行化時(shí)城舞,讀寫數(shù)據(jù)則會鎖住整張表;
題
(1)mysql 什么情況下行鎖會升級為表鎖
如果我們where條件對索引列進(jìn)行上鎖,不會出現(xiàn);如果我們where條件對非索引列進(jìn)行上鎖寞酿,則會出現(xiàn)表鎖變成行鎖
CREATE TABLE `course` (
`id` varchar(35) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`subject` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`my_like` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`real_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`reg_date` date DEFAULT NULL,
`score` int(255) DEFAULT NULL,
`reg_Valid` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
BEGIN
select * from course where name = '張三1' for update
-- 上述只針對name='張三1'進(jìn)行行鎖家夺,但是會發(fā)現(xiàn)執(zhí)行下面sql會出現(xiàn)等待,說明已經(jīng)升級為表鎖
update course set name = 'summit' where id = 5