Browse Source

week10

master
RinRi 1 year ago
parent
commit
bf5c31a6a1
2 changed files with 254 additions and 0 deletions
  1. +142
    -0
      week10/ex1.sql
  2. +112
    -0
      week10/ex2.sql

+ 142
- 0
week10/ex1.sql View File

@@ -0,0 +1,142 @@
-- PART A
CREATE TABLE accounts (id SERIAL, name VARCHAR(50), credit numeric, currency VARCHAR(10));
INSERT INTO accounts (name, credit, currency) VALUES('Account 1', 1000, 'RUB');
INSERT INTO accounts (name, credit, currency) VALUES('Account 2', 1000, 'RUB');
INSERT INTO accounts (name, credit, currency) VALUES('Account 3', 1000, 'RUB');

BEGIN;
-- T1
UPDATE accounts SET credit=credit-500 WHERE name='Account 1';
UPDATE accounts SET credit=credit+500 WHERE name='Account 3';
SAVEPOINT T1;

-- T2
UPDATE accounts SET credit=credit-700 WHERE name='Account 2';
UPDATE accounts SET credit=credit+700 WHERE name='Account 1';
SAVEPOINT T2;

-- T3
UPDATE accounts SET credit=credit-100 WHERE name='Account 2';
UPDATE accounts SET credit=credit+100 WHERE name='Account 3';
SAVEPOINT T3;

ROLLBACK TO T3;
ROLLBACK TO T2;
ROLLBACK TO T1;

ROLLBACK;

-- PART B
ALTER TABLE accounts ADD COLUMN BankName VARCHAR(30);
UPDATE accounts SET BankName='SberBank' WHERE name='Account 1' OR name='Account 3';
UPDATE accounts SET BankName='Tinkoff' WHERE name='Account 2';
INSERT INTO accounts (name, credit, currency) VALUES('Account 4', 1000, 'RUB');

BEGIN;
-- T1
UPDATE accounts SET credit=credit-500 WHERE name='Account 1';
UPDATE accounts SET credit=credit+500 WHERE name='Account 3';
DO
$do$
BEGIN
IF (SELECT COUNT(DISTINCT BankName) FROM accounts WHERE name='Account 1' OR name='Account 3') >= 2 THEN
UPDATE accounts SET credit=credit-30 WHERE name='Account 1';
UPDATE accounts SET credit=credit+30 WHERE name='Account 4';
END IF;
END
$do$;
SAVEPOINT T1;

-- T2
UPDATE accounts SET credit=credit-700 WHERE name='Account 2';
UPDATE accounts SET credit=credit+700 WHERE name='Account 1';
DO
$do$
BEGIN
IF (SELECT COUNT(DISTINCT BankName) FROM accounts WHERE name='Account 2' OR name='Account 1') >= 2 THEN
UPDATE accounts SET credit=credit-30 WHERE name='Account 2';
UPDATE accounts SET credit=credit+30 WHERE name='Account 4';
END IF;
END
$do$;
SAVEPOINT T2;

-- T3
UPDATE accounts SET credit=credit-100 WHERE name='Account 2';
UPDATE accounts SET credit=credit+100 WHERE name='Account 3';
DO
$do$
BEGIN
IF (SELECT COUNT(DISTINCT BankName) FROM accounts WHERE name='Account 2' OR name='Account 3') >= 2 THEN
UPDATE accounts SET credit=credit-30 WHERE name='Account 2';
UPDATE accounts SET credit=credit+30 WHERE name='Account 4';
END IF;
END
$do$;
SAVEPOINT T3;

ROLLBACK TO T3;
ROLLBACK TO T2;
ROLLBACK TO T1;

ROLLBACK;

-- Part C
CREATE TABLE Ledger (id Serial, fromId int, toId int, fee numeric, amount numeric, transactionDateTime timestamp);
BEGIN;
-- T1
UPDATE accounts SET credit=credit-500 WHERE name='Account 1';
UPDATE accounts SET credit=credit+500 WHERE name='Account 3';
DO
$do$
BEGIN
IF (SELECT COUNT(DISTINCT BankName) FROM accounts WHERE name='Account 1' OR name='Account 3') >= 2 THEN
UPDATE accounts SET credit=credit-30 WHERE name='Account 1';
UPDATE accounts SET credit=credit+30 WHERE name='Account 4';
INSERT INTO Ledger (fromId, toId, fee, amount, transactionDateTime) Values(1, 3, 30, 500, CURRENT_TIMESTAMP);
ELSE
INSERT INTO Ledger (fromId, toId, fee, amount, transactionDateTime) Values(1, 3, 0, 500, CURRENT_TIMESTAMP);
END IF;
END
$do$;
SAVEPOINT T1;

-- T2
UPDATE accounts SET credit=credit-700 WHERE name='Account 2';
UPDATE accounts SET credit=credit+700 WHERE name='Account 1';
DO
$do$
BEGIN
IF (SELECT COUNT(DISTINCT BankName) FROM accounts WHERE name='Account 2' OR name='Account 1') >= 2 THEN
UPDATE accounts SET credit=credit-30 WHERE name='Account 2';
UPDATE accounts SET credit=credit+30 WHERE name='Account 4';
INSERT INTO Ledger (fromId, toId, fee, amount, transactionDateTime) Values(2, 1, 30, 700, CURRENT_TIMESTAMP);
ELSE
INSERT INTO Ledger (fromId, toId, fee, amount, transactionDateTime) Values(2, 1, 0, 700, CURRENT_TIMESTAMP);
END IF;
END
$do$;
SAVEPOINT T2;

-- T3
UPDATE accounts SET credit=credit-100 WHERE name='Account 2';
UPDATE accounts SET credit=credit+100 WHERE name='Account 3';
DO
$do$
BEGIN
IF (SELECT COUNT(DISTINCT BankName) FROM accounts WHERE name='Account 2' OR name='Account 3') >= 2 THEN
UPDATE accounts SET credit=credit-30 WHERE name='Account 2';
UPDATE accounts SET credit=credit+30 WHERE name='Account 4';
INSERT INTO Ledger (fromId, toId, fee, amount, transactionDateTime) Values(2, 4, 30, 100, CURRENT_TIMESTAMP);
ELSE
INSERT INTO Ledger (fromId, toId, fee, amount, transactionDateTime) Values(2, 4, 0, 100, CURRENT_TIMESTAMP);
END IF;
END
$do$;
SAVEPOINT T3;

ROLLBACK TO T3;
ROLLBACK TO T2;
ROLLBACK TO T1;

ROLLBACK;

+ 112
- 0
week10/ex2.sql View File

@@ -0,0 +1,112 @@
CREATE TABLE bank2 (id serial, username VARCHAR(50), fullname VARCHAR(50), balance numeric, Group_id int);
INSERT INTO bank2 (username, fullname, balance, Group_id) VALUES('jones', 'Alice Jones', 82, 1);
INSERT INTO bank2 (username, fullname, balance, Group_id) VALUES('bitdiddl', 'Ben Bitdiddle', 82, 1);
INSERT INTO bank2 (username, fullname, balance, Group_id) VALUES('mike', 'Michael Dole', 73, 2);
INSERT INTO bank2 (username, fullname, balance, Group_id) VALUES('alyssa', 'Alyssa P. Hacker', 79, 3);
INSERT INTO bank2 (username, fullname, balance, Group_id) VALUES('bbrown', 'Bob Brown', 100, 3);

-- Terminal 1
BEGIN;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SELECT * from bank2;
-- id | username | fullname | balance | group_id
-- ----+----------+------------------+---------+----------
-- 1 | jones | Alice Jones | 82 | 1
-- 2 | bitdiddl | Ben Bitdiddle | 82 | 1
-- 3 | mike | Michael Dole | 73 | 2
-- 4 | alyssa | Alyssa P. Hacker | 79 | 3
-- 5 | bbrown | Bob Brown | 100 | 3
SELECT * from bank2;
-- id | username | fullname | balance | group_id
-- ----+----------+------------------+---------+----------
-- 1 | jones | Alice Jones | 82 | 1
-- 2 | bitdiddl | Ben Bitdiddle | 82 | 1
-- 3 | mike | Michael Dole | 73 | 2
-- 4 | alyssa | Alyssa P. Hacker | 79 | 3
-- 5 | bbrown | Bob Brown | 100 | 3
-- Nothing changed after the change in second terminal

-- Terminal 2
BEGIN;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
UPDATE bank2 SET username='ajones' WHERE fullname='Alice Jones';
SELECT * from bank2;
-- id | username | fullname | balance | group_id
-- ----+----------+------------------+---------+----------
-- 2 | bitdiddl | Ben Bitdiddle | 82 | 1
-- 3 | mike | Michael Dole | 73 | 2
-- 4 | alyssa | Alyssa P. Hacker | 79 | 3
-- 5 | bbrown | Bob Brown | 100 | 3
-- 1 | ajones | Alice Jones | 82 | 1
-- The results are different because isolation level read commited allows to read only commited changes
COMMIT;
-- After commitment, they are the same

-- Term 1
UPDATE bank2 SET balance=balance+10 WHERE id=1;
-- Term 2
UPDATE bank2 SET balance=balance+20 WHERE id=1;
-- it waits the commitment from term 1
-- Term 1
COMMIT;
-- Term 2
ROLLBACK;

-- Repetable read
UPDATE bank2 SET username='jones' WHERE fullname='Alice Jones';
-- Term 1
BEGIN;
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT * from bank2;
SELECT * from bank2;
SELECT * from bank2;
UPDATE bank2 SET balance=balance+10 WHERE id=1;
COMMIT;

-- Term 2
BEGIN;
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
UPDATE bank2 SET username='ajones' WHERE fullname='Alice Jones';
COMMIT;
BEGIN;
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
UPDATE bank2 SET balance=balance+20 WHERE id=1;

-- Even after COMMIT on term 2, the data doesn't change on Term 1 because of the transaction isolation repetable read
-- Also after the balance change on the second term this error shows up:ERROR: could not serialize access due to concurrent update

-- PART 2

-- TERM 1
BEGIN;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SELECT * from bank2 WHERE Group_id=2;
SELECT * from bank2 WHERE Group_id=2;
UPDATE bank2 SET balance=balance+15 WHERE Group_id=2;
-- Mike shows up


-- TERM 2
BEGIN;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
UPDATE bank2 SET Group_id=2 WHERE username='bbrown';

-- BOB's balance hasn't change because when READ COMMITTED is set, it's impossible to view changes in other running transaction, so only balance of mike changed

-- REPEATABLE
UPDATE bank2 SET Group_id=3 WHERE username='bbrown';
-- TERM 1
BEGIN;
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT * from bank2 WHERE Group_id=2;
SELECT * from bank2 WHERE Group_id=2;
UPDATE bank2 SET balance=balance+15 WHERE Group_id=2;
-- Mike shows up


-- TERM 2
BEGIN;
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
UPDATE bank2 SET Group_id=2 WHERE username='bbrown';

-- THE same result

Loading…
Cancel
Save