Data Acquisition, Extraction & Storage — ENS / Inria / PSL

Storage 2 and 3 Recap Q&A — Relational vs. non-Relational

🔒 Answers locked
Part 1 · Normal forms
Q1

From an Unnormalised Table to 3NF

A secretariat keeps its course registrations in the following table. Each student belongs to one programme, each programme has one director, each course is taught by one lecturer, and each lecturer has one office.

StudentIDNameProgrammeDirectorCourses (code, title, lecturer, office, grade)
S01Léa MartinComputer ScienceProf. Laurent
DB101DatabasesDr. RossiC-21016
IR201Information RetrievalDr. RossiC-21014
S02Hugo BernardMathematicsProf. Moreau
DB101DatabasesDr. RossiC-21012
S03Inès PetitComputer ScienceProf. Laurent
ML301Machine LearningDr. ChenB-10518
DB101DatabasesDr. RossiC-21015

(a) Is this table in first normal form? Rewrite it in 1NF and give its primary key.

(b) List the functional dependencies that hold between the attributes.

(c) Decompose the table into 2NF, then into 3NF. Draw the final schema with its primary and foreign keys.

(d) Give one insertion, one update and one deletion anomaly that the 1NF table suffers from and that your 3NF schema avoids.

Q2

Designing a Relational Schema from a Specification

A regional train operator asks you to design the database behind its booking website. The product owner sends you the following list of what must be stored:

  • Passengers: name, e-mail, date of birth, age, one or more phone numbers, and an optional loyalty card. Each card has a tier (Bronze, Silver, Gold), and each tier gives a fixed discount rate.
  • Stations: a unique code (e.g. RNS), a name, the city it is in, and the city's region.
  • Trains: a train number (e.g. TER 8412) that always follows the same route, which is an ordered list of stations with a scheduled departure time at each. Each train uses a type of rolling stock, which determines the number of 1st- and 2nd-class seats.
  • A train runs on many dates. The run of one train on one date is called a service.
  • Bookings: a reference, the passenger who made the booking, the booking time, the payment method and the total amount paid. A booking contains one or more tickets. Each ticket is for one traveller (not necessarily the person who booked), on one service, from one station to another, in one class, with a coach and seat number and the price paid.

Design a relational schema in 3NF. For each table, give its primary key and foreign keys, and justify every split with the dependency that motivates it. Some of the requested attributes should not be stored as such. Which ones, and why?

Part 2 · Distribution, CAP & consistency
Q3

CP, AP or CA?

Three distributed key-value stores handle reads and writes as follows.

System A: majority replicas

A key is stored on 3 replicas. A write is acknowledged only once at least 2 of the 3 replicas have stored it. A read asks at least 2 replicas and returns the value with the highest version number. A replica that cannot reach at least one other replica answers every request with an error.

R3R1R2write(x)replicateack when ≥ 2 of 3 stored
System B: local first

Each of the 3 replicas accepts any read or write and answers immediately from its local copy. Writes are forwarded to the other replicas in the background whenever they are reachable. When two versions of a key meet, the one with the latest timestamp wins.

R3R1R2r/wr/wr/w"replicate", in background
System C: one rack, all-or-nothing

Two replicas sit in the same rack, linked by a dedicated cable. A write is applied on both replicas with a two-phase commit before being acknowledged, and a read can be served by either one. The designers assume the cable never fails: the protocol has no timeout and no rule for a replica that stops answering.

same rack, one dedicated cableR1R22PC: both applywrite → ack only if R1 AND R2 commit

(a) Classify each system as CP, AP or CA. Justify each answer by describing what happens when the network between replicas is cut.

(b) Which system would you pick for (i) the "like" counter of a social network, (ii) the seat inventory of a train booking system, and (iii) a bank system?

Q4

Making Two Systems Eventually Consistent

Consider two replicated systems that store a single value x (initially 0). The diagrams show each system in normal operation.

System 1. A client writes to any replica, which applies the write locally and acknowledges immediately. The replica then sends the new value to the other replica in one UDP message, without waiting for any reply.

Client AReplica R1x = 0Replica R2x = 0Client Bt1write x = 5x := 5acksend x = 5 (UDP)t2read xx = 0x := 5t3read xx = 5

System 2. Leader–follower with synchronous replication. The leader handles writes one at a time, in arrival order, and commits a write only after every follower has acknowledged it. Reads can go to any follower. Follower F2 is in another data centre.

Client ALeader LFollower F1Follower F2far awayClient Bwaiting for ALL ackswrite x = 5replicate xackreplicate x (slow link)write y = 7y = 7 must waitackcommit x = 5acknow replicate y = 7, wait for all acks…ack (much later)latency Alatency B

(a) In System 1, Client B first reads 0, then reads 5. Is System 1 eventually consistent? More generally, which consistency level seen in class (strong, eventual, low) does each system provide? Think about what can go wrong, not only about the normal case shown.

(b) In System 2 nothing fails, yet Client B waits a long time for its write. Where does this latency come from, and how does it grow with the number and distance of followers? Which theorem from the lecture describes this trade-off?

(c) Modify both systems so that they become eventually consistent.

Part 3 · ACID: atomicity, isolation, durability
Recall
Atomicity: a transaction is either carried out entirely or not at all. If it fails, the database returns to the state before it started.
Isolation: concurrent transactions cannot compromise each other while they are in progress. The result must be as if they ran one after the other.
Q5

Breaking Atomicity

A logistics company moves 50 units of stock from its Paris warehouse (A = 80) to its Lyon warehouse (B = 30). The transfer is one transaction T made of two threads of execution, which the DBMS may interleave in any order. Each Write updates the value in place on disk. There is no log.

#
Thread 1
Thread 2
1
Read(A)
Read(B)
2
A = A − 50
B = B + 50
3
Write(A)
Write(B)

The invariant is A + B = 110. The machine can lose power at any moment.

(a) How many different execution orders (interleavings of the two threads) are possible?

(b) Give one execution order and one moment of failure such that, after restart, the database is in a state that violates atomicity. Give the values of A and B on disk.

(c) Is there an execution order that is safe whatever the moment of failure?

Q6

The Write-Ahead Log: Why It Works and Why It Is Fast Enough

We now add a write-ahead log (WAL), an append-only file on disk. For the transfer of Q5, the DBMS appends the following records:

Transaction log (on disk, append-only)<T, START><T, A, old=80, new=30><T, B, old=30, new=80><T, COMMIT>next appendData pages (on disk, updated in place, later)page of AA = 80page of BB = 30Rule 1 (write-ahead): a log record reaches diskbefore the page it describes.Rule 2: T is committed ⇔ <T, COMMIT> is on disk.

(a) Replay the failure from your answer to Q5(b) with the WAL. What is in the log at the time of the crash, and what does the recovery procedure do at restart? Do the same for a crash that happens just after <T, COMMIT> reaches the disk, but before any data page is written.

(b) Why does the log store the old and new values (old=80, new=30) rather than the operation (A −= 50)?

(c) In the lecture we saw that disk is slow. Yet the WAL adds one more disk write per update. Is WAL still a good solution?

Q7

Isolation Levels and Their Anomalies

Recall the four isolation levels, in their lock-based implementation:

LevelWrite locksRead locksRange locks
0 · Read uncommittedheld until the end of the transactionnonenone
1 · Read committedheld until the end of the transactionreleased right after the readnone
2 · Repeatable readheld until the end of the transactionheld until the end of the transactionnone
3 · Serializableheld until the end of the transactionheld until the end of the transactionon ranged WHERE clauses

A transaction (T1, T2, …) is everything between BEGIN and COMMIT or ROLLBACK. A read lock (shared) can be held by several transactions at once. A write lock (exclusive) excludes every other lock on the same data, so a transaction that asks for a conflicting lock waits. Level 3 adds range locks on top of level 2; we come back to them in Q8.

Table accounts(id, owner, balance) initially contains (1, 'Alice', 100) and (2, 'Bob', 50). Each scenario below starts from this state. For each scenario:

  1. give the value marked ? under the three first levels (and say when a transaction has to wait);
  2. give the lowest isolation level that prevents it.

Scenario 1

t
T1
T2
1
BEGIN;
2
BEGIN;
UPDATE accounts SET balance = 0 WHERE id = 1;
3
SELECT balance FROM accounts WHERE id = 1; -- ?
4
ROLLBACK;
5
COMMIT;

Scenario 2

t
T1
T2
1
BEGIN;
SELECT balance FROM accounts WHERE id = 1; -- 100
2
BEGIN;
UPDATE accounts SET balance = 150 WHERE id = 1;
COMMIT;
3
SELECT balance FROM accounts WHERE id = 1; -- ?
4
COMMIT;

Scenario 3: Bob deposits 30 (T1) while a payment of 20 is debited (T2). The application reads the balance, computes the new value, and writes it back.

t
T1 (deposit +30)
T2 (debit −20)
1
BEGIN;
SELECT balance FROM accounts WHERE id = 2; -- 50
2
BEGIN;
SELECT balance FROM accounts WHERE id = 2; -- 50
3
UPDATE accounts SET balance = 80 WHERE id = 2;
COMMIT;
4
UPDATE accounts SET balance = 30 WHERE id = 2;
COMMIT;
5
Final balance of Bob? -- ?
Q8

What Exactly Should We Lock?

In Q7, level 3 (Serializable) was defined as level 2 plus range locks on ranged WHERE clauses. This question looks at why row locks are not enough, and what a range lock actually is.

Table employees(id, name, dept, salary) has a B-tree index on salary and contains:

id1234567
nameAnaBilalChloéDavidEmmaFaridGaëlle
salary2100280031003400390045006000

A reporting transaction T1 runs the following query twice, and must get the same answer both times:

SELECT COUNT(*), SUM(salary) FROM employees WHERE salary BETWEEN 3000 AND 4000;  -- 3, 10400

Between the two executions, the following transactions try to run:

  • T2: INSERT (8, 'Hugo', 'IT', 3500)
  • T3: UPDATE employees SET salary = 6200 WHERE id = 7 (6000 → 6200)
  • T4: UPDATE employees SET salary = 3200 WHERE id = 2 (2800 → 3200)
  • T5: INSERT (9, 'Inès', 'HR', 5200)
  • T6: INSERT (10, 'Jules', 'IT', 4200)

Two locking procedures are proposed for T1's SELECT:

  • Procedure A: take a shared lock on the whole table until commit. Any writer needs an exclusive lock on the table.
  • Procedure B: take a shared lock on each row that satisfies the WHERE clause until commit. A writer needs an exclusive lock on the rows it modifies or inserts.
WHERE salary BETWEEN 3000 AND 4000T2 ins 3500T6 ins 4200T5 ins 5200T4 2800→3200T3 6000→6200index(salary)2100280031003400390045006000A · table lockwhole table (incl. future rows)B · row locksexisting rows within range

(a) For each procedure, which of T2–T6 are blocked, and what does T1's second SELECT return?

(b) Show that one procedure is too strong and the other too weak.

(c) Design a procedure C in between.

Q9

Durability: The Order of Operations

A client sends UPDATE accounts SET balance = 80 WHERE id = 2; COMMIT; to a modern DBMS. The arrows below are labelled with letters in random order (both arrows marked G belong to the same step):

RAM (volatile)Disk (persistent)ClientDatabase processBuffer pool (cached pages)Transaction log (WAL)Database filesCDGEGBAFH
  • A: append <T, COMMIT> to the log and flush it to disk (fsync)
  • B: write the "new" page to the database files
  • C: the client sends the SQL query
  • D: return "OK" to the client
  • E: apply the change to the page in the buffer pool and mark the page "new"
  • F: write a checkpoint record in the log
  • G: look up the page in the buffer pool; if it is not there, read it from the database files and load it into the buffer
  • H: append the change record <T, page, old=50, new=80> to the log

(a) Put the steps in an order that guarantees atomicity and durability. can we apply any step in the background?

(b) For durability, can we keep the database only in memory? Can we keep the log only in memory?

(c) What goes wrong if B happens before H? What goes wrong if D happens before A?

(d) The power fails while B is writing several "new" pages, so half of them are on disk. What does the DBMS do at restart?

(e) What is step F for? What would happen without it?

Part 4 · Graph databases
Q10

Finding a Route with Relational Databases

Go back to the 3NF train schema of Q2. Routes are stored in RouteStop(train_no, stop_order, station_code, dep_time), one row per stop. An excerpt:

train_nostop_orderstation_codedep_time
TER 84121NTE (Nantes)06:10
TER 84122RNS (Rennes)07:25
TGV 86121RNS (Rennes)07:40
TGV 86122LAV (Laval)08:07
TGV 86123LMN (Le Mans)08:30
TGV 86124PMO (Paris-Montparnasse)09:07
TGV 95751PST (Paris-Est)10:25
TGV 95752STG (Strasbourg)12:12

The network has about 3,000 stations and 10,000 trains of about 15 stops each, so roughly 150,000 rows. A customer asks: "How do I get from one station to another?"

(a) Can you write a query that lists the trains going directly from Rennes to Le Mans?

(b) Now the customer accepts changes: find any itinerary from Nantes to Paris-Montparnasse. Can you write such a query?

(c) Can you write a query that find paths from Rennes to Strasbourg?

Q11

The Railway Network as a Graph

The operator decides to store its network in a graph database, to answer route queries like those of Q10.

(a) Propose a labelled property graph (LPG) for the network. What are the nodes, the relationships, their labels and their properties? Draw the part of the network that is necessary to answer questions from Q10.

(b) Can we move everything (passengers, bookings, tickets, payments) to the graph database?