假设学校允许学生将银行卡和校园卡进行绑定,在student数据库中有如下的基本表,其中校园卡编号cardid即为学生的学号:
create table icbc_card(
icbcid int,
sno varchar(8),
balance int
);
create table campus_card(
sno varchar(8),
balance int
);
insert into campus_card values ('20200032', 1);
insert into campus_card values ('20200033', 100);
insert into icbc_card values (1, '20200032', 300);
insert into icbc_card values (2, '20200033', 400);
针对以上数据库按照要求完成下列实验:
CREATE PROCEDURE transfer()
BEGIN
DECLARE icbc_balance INT DEFAULT 0;
SELECT balance
FROM icbc_card
WHERE sno = '20200032'
INTO icbc_balance;
IF icbc_balance > 200
THEN
UPDATE icbc_card
SET balance = balance - 200
WHERE sno = '20200032';
UPDATE campus_card
SET balance = balance + 200
WHERE sno = '20200032';
COMMIT;
ELSE
ROLLBACK;
END IF;
END
两个workbench打开的两个界面都要设置隔离级
set session transaction isolation level READ UNCOMMITTED;
丢失修改:
创建一个先读后写的存储过程
CREATE DEFINER=`root`@`localhost` PROCEDURE `read_and_write`()
BEGIN
DECLARE campus_balance INT DEFAULT 0;
SELECT balance
FROM campus_card
WHERE sno = '20200032'
INTO campus_balance;
SELECT sleep(10);
UPDATE campus_card
SET balance = campus_balance + 1
WHERE sno = '20200032';
END
读写之间用sleep函数留出了10s的时间,你可以打开另一个程序去运行同样的存储过程,查看最后的修改结果。
不可重复读:
先执行1,然后迅速执行2可以看到1读出的balance两次值不同。
CREATE DEFINER=`root`@`localhost` PROCEDURE `non_repeatable_read_1`()
BEGIN
SELECT balance
FROM campus_card
WHERE sno = '20200032';
SELECT sleep(10);
SELECT balance
FROM campus_card
WHERE sno = '20200032';
END
CREATE DEFINER=`root`@`localhost` PROCEDURE `non_repeatable_read_2`()
BEGIN
UPDATE campus_card
SET balance = balance + 1
WHERE sno = '20200032';
END
读脏数据:
CREATE DEFINER=`root`@`localhost` PROCEDURE `dirty_read`()
BEGIN
SELECT balance
FROM campus_card
WHERE sno = '20200032';
END
CREATE DEFINER=`root`@`localhost` PROCEDURE `dirty_write`()
BEGIN
UPDATE campus_card
SET balance = balance + 1
WHERE sno = '20200032';
SELECT SLEEP(10);
ROLLBACK;
END
set session transaction isolation level READ COMMITTED;
(2) 读脏数据
set session transaction isolation level READ COMMITTED;
(3) 不可重复读
set session transaction isolation level REPEATABLE READ;
(4) 幻读(删除和插入)
set session transaction isolation level SERIALIZABLE;
防止查重起见,这个我只说一下思路
lock语句可以对表进行锁定,所以可以分两个进程,一个进程对A表先锁定后更新,另一个进程对B表先锁定后更新,然后两者交换,第一个进程更新B表,第二个进程更新A表,这时它们就会进入死锁状态。
这一段借鉴了学长的代码
start transaction;
insert into icbc_card values(3,'20200034',900);
insert into icbc_card values(4,'20200035',600);
savepoint s1;
insert into icbc_card values(5,'20200036',400);
insert into icbc_card values(6,'20200037',500);
savepoint s2;
insert into icbc_card values(7,'20200038',200);
insert into icbc_card values(8,'20200039',100);
select * from icbc_card;
执行后依次回滚到s2,s1,整个事务;
rollback to savepoint s2;
select * from icbc_card;
rollback to savepoint s1;
select * from icbc_card;
rollback;
select * from icbc_card;
输入以下命令后将给出日志的路径,具体内容可以到指定路径下查看
查询日志:
show variables like 'general_log_file';
错误日志:
show variables like 'log_error';
慢查询日志:
show variables like 'slow_query_log_file';
首先创建日志文件:
flush logs;
show master status;
create database db1;
use db1;
create table t1(id int);
create table t2(id int);
insert into t1 values(11);
insert into t1 values(12);
insert into t1 values(13);
insert into t2 values(21);
insert into t2 values(22);
insert into t2 values(23);
drop table t1;
insert into t2 values(24);
show binlog events in 'binlog.000029';
/*此处的in后面的内容由第一步的查询结果确定*/
使用命令行工具将binlog文件中的sql语句导出(需要使用管理员权限)
这个暂时没跑通,跑通了再更新一下