From 5cbda2dca73e078289a221a3a0594941499cba3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Sch=C3=A4ren?= Date: Sun, 19 Apr 2026 23:20:00 +0200 Subject: [PATCH] handle seminarplatz_vergabe concurrently --- ...-104 Datenbanken und Datenverarbeitung.iml | 2 +- .idea/data_source_mapping.xml | 9 - .idea/misc.xml | 2 +- .idea/sqldialects.xml | 4 - .idea/vcs.xml | 6 + .../Aufgabe_3:_Recherche_zu_SQL_Features.pdf | Bin 66742 -> 0 bytes Block-2/seminarplatz_vergabe.ipynb | 417 ++++++++++++++++++ 7 files changed, 425 insertions(+), 15 deletions(-) delete mode 100644 .idea/data_source_mapping.xml create mode 100644 .idea/vcs.xml delete mode 100644 Block-1/Aufgabe_3:_Recherche_zu_SQL_Features.pdf create mode 100644 Block-2/seminarplatz_vergabe.ipynb diff --git a/.idea/cds-104 Datenbanken und Datenverarbeitung.iml b/.idea/cds-104 Datenbanken und Datenverarbeitung.iml index c69f1c9..d8b3f6c 100644 --- a/.idea/cds-104 Datenbanken und Datenverarbeitung.iml +++ b/.idea/cds-104 Datenbanken und Datenverarbeitung.iml @@ -2,7 +2,7 @@ - + \ No newline at end of file diff --git a/.idea/data_source_mapping.xml b/.idea/data_source_mapping.xml deleted file mode 100644 index c8be428..0000000 --- a/.idea/data_source_mapping.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 5f4a9fa..977706b 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,5 +3,5 @@ - + \ No newline at end of file diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml index 0254c70..6df4889 100644 --- a/.idea/sqldialects.xml +++ b/.idea/sqldialects.xml @@ -1,10 +1,6 @@ - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Block-1/Aufgabe_3:_Recherche_zu_SQL_Features.pdf b/Block-1/Aufgabe_3:_Recherche_zu_SQL_Features.pdf deleted file mode 100644 index 2c102e756035194f465e7ef687213a57eb3a2f41..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66742 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 T)OE*!bODyq(4l75=1Ttuq%J`s diff --git a/Block-2/seminarplatz_vergabe.ipynb b/Block-2/seminarplatz_vergabe.ipynb new file mode 100644 index 0000000..205510c --- /dev/null +++ b/Block-2/seminarplatz_vergabe.ipynb @@ -0,0 +1,417 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Seminarplatz-Vergabe\n", + "\n", + "In folgendem Problem geht es darum, dass eine Gruppe von Studierenden einen oder mehrere Seminarplätze in einem Kurs bekommen sollen. Es gibt 8 Seminargruppen mit insgesamt 40 Plätzen, diese sind in der Tabelle `seminar_sessions` abgelegt.\n", + "\n", + "Bei einer Anmeldung einer einzelnen Person wird die Anzahl der Plätze in der Tabelle `seminar_sessions` um 1 reduziert und ein Eintrag in der Tabelle `seminar_registrations` erstellt. Dies darf natürlich nur passieren, wenn noch Plätze verfügbar sind.\n", + "\n", + "Die Anzahl der vergebenen Plätze in der Tabelle `seminar_registrations` und die Anzahl der verfügbaren Plätze in der Tabelle `seminar_sessions` müssen konsistent sein, also in der Summe 40 ergeben.\n", + "\n", + "In einem Lasttest mit mehreren Threads zeigt sich: Die Anzahl der vergebenen Plätze in der Tabelle `seminar_registrations` und die Anzahl der verfügbaren Plätze in der Tabelle `seminar_sessions` sind nicht konsistent! \n", + "\n", + "### Ihre Aufgabe:\n", + "Führen Sie geeignete Transaktionen ein, um die Konsistenz zu gewährleisten!\n", + "\n", + "Implementierungen Sie dazu zunächst die Funktionen, die mit TODO gekennzeichnet sind, und passen Sie die Funktion `reserve_seat` an, um die Konsistenz zu gewährleisten.\n", + "\n", + "Am Code des Lasttests müssen Sie nichts ändern, er dient nur dazu, das Problem zu demonstrieren.\n", + "\n", + "### Bemerkungen:\n", + "\n", + "- nicht jeder Durchlauf verursacht Inkonsistenzen, manchmal müssen Sie den Code mehrmals ausführen, um Inkonsistenzen zu finden\n", + "- auch Deadlocks können auftreten, diese müssen auch vermieden werden\n", + "- die User-Tabelle wurde weggelassen, da sie für das Problem nicht relevant ist\n", + "- an manchen Stellen ist der Code absichtlich etwas ineffizient gehalten, um die Inkonsistenzen zu begünstigen (z.B. würden Probleme mit Inkonsistenzen seltener auftreten, wenn die Query `UPDATE seminar_sessions SET seats = seats-1` lauten würde).\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2026-04-19T20:28:20.768652Z", + "start_time": "2026-04-19T20:28:20.766464Z" + } + }, + "source": [ + "import psycopg2\n", + "import psycopg2.extras" + ], + "outputs": [], + "execution_count": 26 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2026-04-19T20:28:21.151712Z", + "start_time": "2026-04-19T20:28:21.149462Z" + } + }, + "source": [ + "# Datenbankverbindung herstellen\n", + "def get_connection():\n", + " conn = psycopg2.connect(\"dbname=seminar user=postgres password=sml12345\")\n", + " return conn" + ], + "outputs": [], + "execution_count": 27 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2026-04-19T20:28:37.424939Z", + "start_time": "2026-04-19T20:28:37.390822Z" + } + }, + "source": [ + "# Tabelle erzeugen - immer wenn diese Zelle ausgeführt wird, wird die Tabelle neu erzeugt\n", + "conn = get_connection()\n", + "cursor = conn.cursor()\n", + "cursor.execute(\"\"\"\n", + " DROP TABLE IF EXISTS seminar_registrations CASCADE;\n", + " DROP TABLE IF EXISTS seminar_sessions;\n", + " \n", + " CREATE TABLE IF NOT EXISTS seminar_sessions (\n", + " id SERIAL PRIMARY KEY, \n", + " seats INTEGER NOT NULL\n", + " );\n", + " \n", + " INSERT INTO seminar_sessions (seats) VALUES \n", + " (4), (4), (5), (5), (4), (10), (5), (3);\n", + " \n", + " \n", + " CREATE TABLE IF NOT EXISTS seminar_registrations (\n", + " user_id INTEGER NOT NULL,\n", + " session_id INTEGER NOT NULL,\n", + " FOREIGN KEY (session_id) REFERENCES seminar_sessions(id)\n", + " ); \n", + "\"\"\")\n", + "conn.commit()" + ], + "outputs": [], + "execution_count": 33 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2026-04-19T20:28:22.178605Z", + "start_time": "2026-04-19T20:28:22.174509Z" + } + }, + "source": [ + "# Hilfsfunktion: Alle Seminar-Sessions ausgeben\n", + "def show_sessions():\n", + " cursor.execute(\"SELECT * FROM seminar_sessions\")\n", + " rows = cursor.fetchall()\n", + " print(\"Seminar Sessions:\")\n", + " for row in rows:\n", + " print(row[0], row[1])\n", + "\n", + "\n", + "# Anzahl aller freien Plätze bestimmen\n", + "def count_free_seats():\n", + " cursor.execute(\"SELECT sum(seats) FROM seminar_sessions\")\n", + " return cursor.fetchone()[0]\n", + "\n", + "# Anzahl der belegten Plätze bestimmen\n", + "def count_occupied_seats():\n", + " cursor.execute(\"SELECT count(*) FROM seminar_registrations\")\n", + " return cursor.fetchone()[0]\n", + "\n", + "# Testaufrufe\n", + "\n", + "show_sessions()\n", + "print(\"freie Plätze\", count_free_seats())\n", + "print(\"belegte Plätze\", count_occupied_seats())" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Seminar Sessions:\n", + "1 4\n", + "2 4\n", + "3 5\n", + "4 5\n", + "5 4\n", + "6 10\n", + "7 5\n", + "8 3\n", + "freie Plätze 40\n", + "belegte Plätze 0\n" + ] + } + ], + "execution_count": 29 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2026-04-19T20:28:22.832360Z", + "start_time": "2026-04-19T20:28:22.829458Z" + } + }, + "source": [ + "# Diese Funktion soll einen Platz reservieren und True zurückgeben, wenn es geklappt hat.\n", + "# Wenn kein Platz mehr frei ist, soll False zurückgegeben werden.\n", + "def reserve_seat(conn, user_id, session_id):\n", + " with conn.cursor() as cursor:\n", + " cursor.execute(\"SELECT seats FROM seminar_sessions WHERE id = %s FOR UPDATE\", (session_id,))\n", + " seats = cursor.fetchone()[0]\n", + "\n", + " if seats > 0:\n", + " cursor.execute(\"UPDATE seminar_sessions SET seats = %s WHERE id = %s\", (seats-1, session_id,))\n", + " cursor.execute(\"INSERT INTO seminar_registrations (user_id, session_id) VALUES (%s, %s)\", (user_id, session_id))\n", + " conn.commit()\n", + " return True\n", + " else:\n", + " conn.rollback()\n", + " return False\n", + " \n" + ], + "outputs": [], + "execution_count": 30 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2026-04-19T20:28:23.903374Z", + "start_time": "2026-04-19T20:28:23.900910Z" + } + }, + "source": [ + "import random \n", + "\n", + "# 20 zufällige Anmeldungen durchführen - diese Funktion wird später als Thread gestartet\n", + "def random_seat_reservation(n=20):\n", + " # jeder Thread hat seine eigene Verbindung\n", + " conn = get_connection()\n", + " \n", + " # n mal einen zufälligen Platz für eine zufällige User-ID reservieren\n", + " for _ in range(n):\n", + " random_user_id = random.randint(1, 100)\n", + " random_session_id = random.randint(1, 8)\n", + "\n", + " if reserve_seat(conn, random_user_id, random_session_id):\n", + " print(\"User\", random_user_id, \"hat sich für Session\", random_session_id, \"angemeldet\")\n", + " else:\n", + " print(\"Session\", random_session_id, \"ist ausgebucht\")" + ], + "outputs": [], + "execution_count": 31 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2026-04-19T20:28:40.301148Z", + "start_time": "2026-04-19T20:28:40.248650Z" + } + }, + "source": [ + "import threading\n", + "\n", + "# Diese Funktion gibt Informationen über die Belegung der Seminare aus\n", + "def print_info():\n", + " print('-'*20)\n", + " \n", + " free_seats = count_free_seats()\n", + " occupied_seats = count_occupied_seats()\n", + "\n", + " print(\"Freie Plätze:\", free_seats)\n", + " print(\"Belegte Plätze:\", occupied_seats)\n", + " print(\"Gesamt:\", free_seats + occupied_seats)\n", + " \n", + " if free_seats + occupied_seats == 40:\n", + " print(\"Platzanzahl ist konsistent!\")\n", + " else:\n", + " print(\"Platzanzahl ist inkonsistent!\")\n", + "\n", + " print('-'*20)\n", + "\n", + "# -------------------------------------------------------------------------\n", + "# Mini-Lasttest, 5 Threads starten, die jeweils 20 Reservierungen vornehmen\n", + "# -------------------------------------------------------------------------\n", + "\n", + "print(\"Vor dem Lasttest:\")\n", + "print_info()\n", + "\n", + "threads = [ threading.Thread(target=random_seat_reservation) for _ in range(5)]\n", + "\n", + "# Threads starten\n", + "for t in threads:\n", + " t.start()\n", + "\n", + "# Auf das Ende der Threads warten\n", + "for t in threads:\n", + " t.join()\n", + "\n", + " \n", + "print(\"Nach dem Lasttest:\")\n", + "print_info()" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Vor dem Lasttest:\n", + "--------------------\n", + "Freie Plätze: 40\n", + "Belegte Plätze: 0\n", + "Gesamt: 40\n", + "Platzanzahl ist konsistent!\n", + "--------------------\n", + "User 50 hat sich für Session 2 angemeldet\n", + "User 42 hat sich für Session 5 angemeldet\n", + "User 59 hat sich für Session 5 angemeldet\n", + "User 33 hat sich für Session 8 angemeldet\n", + "User 6 hat sich für Session 2 angemeldet\n", + "User 30 hat sich für Session 3 angemeldet\n", + "User 14 hat sich für Session 5 angemeldet\n", + "User 75 hat sich für Session 1 angemeldet\n", + "User 44 hat sich für Session 8 angemeldet\n", + "User 42 hat sich für Session 5 angemeldet\n", + "User 87 hat sich für Session 7 angemeldet\n", + "User 44 hat sich für Session 4 angemeldet\n", + "User 87 hat sich für Session 2 angemeldet\n", + "User 64 hat sich für Session 2 angemeldet\n", + "User 83 hat sich für Session 1 angemeldet\n", + "User 54 hat sich für Session 1 angemeldet\n", + "User 47 hat sich für Session 3 angemeldet\n", + "User 23 hat sich für Session 1 angemeldet\n", + "Session 2 ist ausgebucht\n", + "User 91 hat sich für Session 4 angemeldet\n", + "User 22 hat sich für Session 3 angemeldet\n", + "Session 2 ist ausgebucht\n", + "Session 2 ist ausgebucht\n", + "User 86 hat sich für Session 3 angemeldet\n", + "User 36 hat sich für Session 4 angemeldet\n", + "Session 2 ist ausgebucht\n", + "Session 5 ist ausgebucht\n", + "User 1 hat sich für Session 8 angemeldet\n", + "Session 1 ist ausgebucht\n", + "User 3 hat sich für Session 4 angemeldet\n", + "User 85 hat sich für Session 7 angemeldet\n", + "Session 2 ist ausgebucht\n", + "User 32 hat sich für Session 6 angemeldet\n", + "Session 5 ist ausgebucht\n", + "Session 2 ist ausgebucht\n", + "User 29 hat sich für Session 3 angemeldet\n", + "User 58 hat sich für Session 6 angemeldet\n", + "User 75 hat sich für Session 7 angemeldet\n", + "User 50 hat sich für Session 4 angemeldet\n", + "Session 2 ist ausgebucht\n", + "Session 5 ist ausgebucht\n", + "Session 4 ist ausgebucht\n", + "User 99 hat sich für Session 6 angemeldet\n", + "User 82 hat sich für Session 7 angemeldet\n", + "Session 3 ist ausgebucht\n", + "Session 2 ist ausgebucht\n", + "Session 5 ist ausgebucht\n", + "Session 2 ist ausgebucht\n", + "Session 2 ist ausgebucht\n", + "Session 8 ist ausgebucht\n", + "Session 5 ist ausgebucht\n", + "Session 2 ist ausgebucht\n", + "Session 5 ist ausgebucht\n", + "Session 2 ist ausgebucht\n", + "Session 3 ist ausgebucht\n", + "Session 1 ist ausgebucht\n", + "Session 1 ist ausgebucht\n", + "User 67 hat sich für Session 6 angemeldet\n", + "Session 5 ist ausgebucht\n", + "Session 5 ist ausgebucht\n", + "User 53 hat sich für Session 7 angemeldet\n", + "Session 3 ist ausgebucht\n", + "Session 7 ist ausgebucht\n", + "Session 8 ist ausgebucht\n", + "Session 8 ist ausgebucht\n", + "Session 8 ist ausgebucht\n", + "Session 7 ist ausgebucht\n", + "Session 1 ist ausgebucht\n", + "Session 2 ist ausgebucht\n", + "Session 4 ist ausgebucht\n", + "Session 8 ist ausgebucht\n", + "Session 3 ist ausgebucht\n", + "Session 3 ist ausgebucht\n", + "Session 2 ist ausgebucht\n", + "Session 7 ist ausgebucht\n", + "Session 4 ist ausgebucht\n", + "User 12 hat sich für Session 6 angemeldet\n", + "Session 4 ist ausgebucht\n", + "Session 4 ist ausgebucht\n", + "Session 3 ist ausgebucht\n", + "User 68 hat sich für Session 6 angemeldet\n", + "Session 5 ist ausgebucht\n", + "Session 8 ist ausgebucht\n", + "Session 7 ist ausgebucht\n", + "Session 2 ist ausgebucht\n", + "User 18 hat sich für Session 6 angemeldet\n", + "Session 3 ist ausgebucht\n", + "Session 4 ist ausgebucht\n", + "User 56 hat sich für Session 6 angemeldet\n", + "Session 1 ist ausgebucht\n", + "Session 7 ist ausgebucht\n", + "Session 4 ist ausgebucht\n", + "Session 8 ist ausgebucht\n", + "Session 1 ist ausgebucht\n", + "User 88 hat sich für Session 6 angemeldet\n", + "Session 7 ist ausgebucht\n", + "Session 5 ist ausgebucht\n", + "Session 5 ist ausgebucht\n", + "Session 2 ist ausgebucht\n", + "User 28 hat sich für Session 6 angemeldet\n", + "Nach dem Lasttest:\n", + "--------------------\n", + "Freie Plätze: 0\n", + "Belegte Plätze: 40\n", + "Gesamt: 40\n", + "Platzanzahl ist konsistent!\n", + "--------------------\n" + ] + } + ], + "execution_count": 34 + }, + { + "metadata": {}, + "cell_type": "code", + "outputs": [], + "execution_count": null, + "source": "" + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}