module 4: implementing transactional replication
TRANSCRIPT
![Page 1: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/1.jpg)
Module 4:Implementing Transactional Replication
![Page 2: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/2.jpg)
Overview
Understanding Transactional Replication Architecture
Replicating with Transactional Replication
Implementing Updatable Transactional Replication
Facilitating Transactional Replication by Using Stored Procedures
Troubleshooting Transactional Replication
Tuning Transactional Replication
![Page 3: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/3.jpg)
Lesson: Understanding Transactional Replication Architecture
How Transactional Replication Moves Data
The Role of the Log Reader Agent
How the Log Reader Agent Reads the Transaction Log
How the Log Reader Agent Changes Transaction Syntax
The Role of the Distribution Agent
Independent and Shared Agents
Concurrent Snapshot Generation
![Page 4: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/4.jpg)
How Transactional Replication Moves Data
Snapshot ensures synchronized table schema and dataSnapshot ensures synchronized table schema and data
Log Reader Agent scans transaction logLog Reader Agent scans transaction log
Log Reader Agent copies transactions marked for replication to DistributorLog Reader Agent copies transactions marked for replication to Distributor
Distribution Agent moves transactions from Distributor to SubscribersDistribution Agent moves transactions from Distributor to Subscribers
![Page 5: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/5.jpg)
The Role of the Log Reader Agent
1111 The Log Reader Agent is created when the first transactional publication is created on the Publisher
Log Reader Log Reader AgentAgent
Log Reader Log Reader AgentAgentCreatedCreatedCreatedCreated2222 The Log Reader Agent looks
in the distribution database for the last LSN read
Each time the Log Reader Agent runs:
3333 The Log Reader Agent reads the transaction log of the publishing database starting with the next LSN
distributiondistribution
LSN: 18
Transaction log
Transaction log
1111 The Log Reader Agent is created when the first transactional publication is created on the Publisher
Log Reader Log Reader AgentAgent
Log Reader Log Reader AgentAgent
2222 The Log Reader Agent looks in the distribution database for the last LSN read
Each time the Log Reader Agent runs:
3333 The Log Reader Agent reads the transaction log of the publication database starting with the next LSN
distributiondistribution
LSN: 18
Transaction log
Transaction log
11 3322
![Page 6: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/6.jpg)
How the Log Reader Agent Reads the Transaction Log
1111 Finds the next LSN
2222 Starts reading transactions
3333 Ignores transactions related to nonpublished objects
4444 Copies the published transactions to the distribution database
5555 Marks the log as transactions read to here
LSN:************** 29: XXXXX
LSN:************** 17: UPDATELSN:************** 18: XXXXX LSN:************** 19: UPDATE LSN:************** 20: UPDATE LSN:************** 21: INSERTLSN:************** 22: DELETELSN:************** 23: UPDATELSN:************** 24: INSERTLSN:************** 25: INSERTLSN:************** 26: UPDATE LSN:************** 27: INSERT LSN:************** 28: INSERT
UPDATEUPDATEINSERTUPDATE …
6666 Anything prior to the mark can be truncated
11 3322
![Page 7: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/7.jpg)
How the Log Reader Agent Changes Transaction Syntax
INSERT INTO Emp VALUES (57, 'Bremer', 'Ted') INSERT INTO Emp VALUES (57, 'Bremer', 'Ted')
CALL sp_MSins_Emp (57, 'Bremer', 'Ted') CALL sp_MSins_Emp (57, 'Bremer', 'Ted') May convert to astored procedureMay convert to astored procedure
UPDATE XYZ SET …UPDATE XYZ SET …
DELETE XYZ …INSERT XYZ …
DELETE XYZ …INSERT XYZ …
May convert to anDELETE/INSERT
May convert to anDELETE/INSERT
UPDATE Emp SET Phone = '5559521' WHERE LastName = 'Bremer' AND FirstName = 'Ted'
UPDATE Emp SET Phone = '5559521' WHERE LastName = 'Bremer' AND FirstName = 'Ted'
CALL sp_MSupd_Emp (57, '5559521') CALL sp_MSupd_Emp (57, '5559521') Uses primary keyUses primary key
11 3322
![Page 8: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/8.jpg)
The Role of the Distribution Agent
distribution database
distribution database
subscribing database
subscribing database
subscribing database
subscribing database
Distribution Distribution AgentAgent
Distribution Distribution AgentAgent
DTSPackage
DTSDTSData PumpData Pump
DTSDTSData PumpData Pump
Transformable subscriptions only
Transformable subscriptions only
11 3322
![Page 9: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/9.jpg)
subscribing database
subscribing database
subscribing database
subscribing database
Independent and Shared Agents
Shared Agent
Shared Agent
Independent Agent
Independent Agent
Independent Agent
Independent Agent
![Page 10: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/10.jpg)
Concurrent Snapshot Generation
Marks the log
Copies the tables
Marks the log
Checks the log between the marks for transactions marked for replication
Applies the initial snapshot
Applies the transactions copied from the marked portion of the log
Publishing Database
Transaction log
Transaction log
INSERT…X
Subscribing Database
Tablesprocsviews
Tablesprocsviews
Distributor
SQLSQL
1111
2222
3333
4444
5555
6666
X
INSERT…
INSERT…
11 3322
![Page 11: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/11.jpg)
Lesson: Replicating with Transactional Replication
Designing Tables for Transactional Replication
Replicating text, ntext, and image Data
Replicating Horizontally Filtered Data
Overhead of Filtering for Transactional Replication
![Page 12: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/12.jpg)
Designing Tables for Transactional Replication
Y Related row
INSERT X, Y, Z
Insert on Publisher checks the relationship
Insert on Publisher checks the relationship
It is not necessary to check again on the Subscriber
It is not necessary to check again on the Subscriber
ReplicationReplicationReplicationReplication
ReplicationReplicationReplicationReplication
Use NOT FOR REPLICATION for relationshipsUse NOT FOR REPLICATION for relationshipsUse NOT FOR REPLICATION for relationshipsUse NOT FOR REPLICATION for relationships
11 3322
Y Related row
INSERT X, Y, Z
![Page 13: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/13.jpg)
Practice: Designing Tables for Transactional Replication
Adding syntax
ALTER TABLE and CLUSTERED INDEX
ALTER TABLE and FOREIGN KEY
CREATE TRIGGER
![Page 14: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/14.jpg)
Replicating text, ntext, and image Data
Reinitialize the publication if nonlogged operations have occurred
Use the WITH LOG option with text operations
Use max text repl size with ODBC subscribers
![Page 15: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/15.jpg)
Replicating Horizontally Filtered Data
CREATE PROCEDURE CustFilter FOR REPLICATION ASIF EXISTS ( SELECT Country FROM Customers WHERE Country IN (SELECT Country FROM Promotion (NOLOCK)) RETURN 1ELSE RETURN 0
CREATE PROCEDURE CustFilter FOR REPLICATION ASIF EXISTS ( SELECT Country FROM Customers WHERE Country IN (SELECT Country FROM Promotion (NOLOCK)) RETURN 1ELSE RETURN 0
![Page 16: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/16.jpg)
Overhead of Filtering in Transactional Replication
Number of filters
Every row tested against every filter
Each filter is evaluated independently
Complexity
Complexity determines overhead
Joins, functions, comparisons, and indexes contribute to overhead
![Page 17: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/17.jpg)
Lesson: Implementing Updatable Transactional Replication
What Are Updating Subscriptions?
Limitations of Updating Subscriptions
How Subscribers Using Immediate Updating Subscriptions Update Tables
Schema Alterations for Subscribers Using Immediate Updating Subscriptions
Choosing a Queue Type
How Queued Updating Subscriptions Update Tables (SQL Server 2000 queue)
How Queued Updating Subscriptions Update Tables (MSMQ)
Managing Conflicts with Subscribers Using Queued Updating Subscriptions
Implementing Immediate Updating with Failover to Queued Updating
Managing Identity Values for Updating Subscriptions
![Page 18: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/18.jpg)
Subscriber using immediate updating
subscription
Subscriber using queued
updating subscription
What Are Updating Subscriptions?
Publisher
Distributor
Queue Reader Agent
Reliable Connection
Reliable Connection
Queue
IntermittentConnectionIntermittentConnection
11 3322
![Page 19: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/19.jpg)
Limitations of Updating Subscriptions
No merge replication
No republishing replicated data at the Subscriber
All text and image data should be treated as read-only
Cannot disable the updating subscription
Cannot use INSERT statements without a column list
Cannot combine with transformable subscriptions
Cannot use pre-existing data at Subscribers
![Page 20: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/20.jpg)
How Subscribers Using Immediate Updating Subscriptions Update Tables
Publisher updates table and forwards transactionsPublisher updates table and forwards transactions
Subscriber starts transaction and connects with MS DTCSubscriber starts transaction and connects with MS DTC
MS DTC completes data modification with two-phase commit (2PC)MS DTC completes data modification with two-phase commit (2PC)
Publisher distributes update to other Subscribers according to schedulePublisher distributes update to other Subscribers according to schedule
![Page 21: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/21.jpg)
Schema Alterations for Subscribers Using Immediate Updating Subscriptions
MSrepl_tran_version
Added by wizard if needed
Include vertical filter
Add to column list
System-defined triggers
Added automatically when subscribers enabled
Make calls to MS DTC
Avoiding a trigger-firing loop
Fire user-defined triggers after immediate updating triggers
![Page 22: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/22.jpg)
Choosing a Queue Type
SQL Server 2000 queue
Works with all SQL Server platforms
Easy to set up
No additional components to install
Faster
Microsoft Message Queue (MSMQ)
Centralized queue administration and monitoring
Propagate changes when Subscriber is not running SQL Server
Does not require available Publisher when Subscriber reconnects
![Page 23: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/23.jpg)
Publisher updates table and forwards transactions using typical transactional replicationPublisher updates table and forwards transactions using typical transactional replication
Subscriber trigger places copy of new transactions in MSreplication_queueSubscriber trigger places copy of new transactions in MSreplication_queue
SQL Server Queue Reader Agent checks for new rows to be moved to Distributor queueSQL Server Queue Reader Agent checks for new rows to be moved to Distributor queue
SQL Server Queue Reader Agent uses MS DTC to move rows to PublisherSQL Server Queue Reader Agent uses MS DTC to move rows to Publisher
Publisher distributes update to other SubscribersPublisher distributes update to other Subscribers
SQL Server 2000 Queue:SQL Server 2000 Queue:SQL Server 2000 Queue:SQL Server 2000 Queue:
How Queued Updating Subscriptions Update Tables (SQL Server 2000 Queue)
![Page 24: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/24.jpg)
Publisher updates table and forwards transactions using typical transactional replicationPublisher updates table and forwards transactions using typical transactional replication
MSMQ places transaction in MSMQ-managed queueMSMQ places transaction in MSMQ-managed queue
MSMQ service on Subscriber moves row to MSMQ service on Distributor by using MS DTCMSMQ service on Subscriber moves row to MSMQ service on Distributor by using MS DTC
MSMQ service on Distributor connects to Publisher and updates Subscriber table by using MS DTCMSMQ service on Distributor connects to Publisher and updates Subscriber table by using MS DTC
Publisher distributes update to other SubscribersPublisher distributes update to other Subscribers
MSMQ:MSMQ:MSMQ:MSMQ:
How Queued Updating Subscriptions Update Tables (MSMQ)
![Page 25: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/25.jpg)
Managing Conflicts with Subscribers Using Queued Updating Subscriptions
How SQL Server detects conflicts
Choosing a conflict resolver
Keep change made at Publisher
Keep change made at Subscriber
Reinitialize the subscription
![Page 26: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/26.jpg)
Implementing Immediate Updating with Failover to Queued Updating
Immediate updatingImmediate updatingImmediate updatingImmediate updating
1111 Using immediate updating
2222 Connection is unavailable
3333 Switch to queuing
4444 When connection is available – empty the queue
5555 Resume immediate updating
11 3322
QueueQueue1.
2.
3.
4.
4. 3. 2. 1. 4. 3. 2. 1.
![Page 27: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/27.jpg)
Managing Identity Values for Updating Subscriptions
Methods for managing identity values
Use SQL Server 2000 automatic management Use the NOT FOR REPLICATION option Use a primary key other than the identity column
Identity values and immediate updating
Publisher controls identity values You cannot assign identity ranges
Identity values and queued updating
Assigned by the Subscriber Identity values and queued updating failover
Assign identity ranges to Subscribers Inserted rows generate identity values from the range
![Page 28: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/28.jpg)
Lesson: Facilitating Transactional Replication by Using Stored Procedures
Understanding Custom Stored Procedures for Replication
Creating Custom Stored Procedures
Implementing Custom Stored Procedures
![Page 29: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/29.jpg)
Understanding Custom Stored Procedures for Replication
Benefits of custom stored procedures
Improved performance Less data passed over the network
Command types
CALL MCALL XCALL SQL NONE
![Page 30: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/30.jpg)
Creating Custom Stored Procedures
sp_scriptinsproc
sp_scriptdelproc
sp_scriptupdproc
sp_scriptmappedupdproc
sp_scriptdynamicupdproc
sp_scriptpublicationcustomprocs
![Page 31: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/31.jpg)
Implementing Custom Stored Procedures
![Page 32: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/32.jpg)
Lesson: Troubleshooting Transactional Replication
Troubleshooting by Using the Distribution and Log Reader Agents
Troubleshooting by Using Stored Procedures
Skipping Errors to Prevent Replication Halts
Reinitializing Subscriptions
Troubleshooting Steps
Troubleshooting Guidelines
![Page 33: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/33.jpg)
Troubleshooting by Using the Distribution and Log Reader Agents
"C:\Program Files\Microsoft SQL Server\80\COM\logread" -Publisher [VANCOUVER] -PublisherDB [Northwind] -DistributorSecurityMode 1
"C:\Program Files\Microsoft SQL Server\80\COM\logread" -Publisher [VANCOUVER] -PublisherDB [Northwind] -DistributorSecurityMode 1
"C:\Program Files\Microsoft SQL Server\80\COM\distrib" -Publisher [VANCOUVER] -PublisherDB [Northwind] -Publication [CustomersTransactional] -DistributorSecurityMode 1
"C:\Program Files\Microsoft SQL Server\80\COM\distrib" -Publisher [VANCOUVER] -PublisherDB [Northwind] -Publication [CustomersTransactional] -DistributorSecurityMode 1
Log Reader AgentLog Reader AgentLog Reader AgentLog Reader Agent
Distribution AgentDistribution AgentDistribution AgentDistribution Agent
![Page 34: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/34.jpg)
Troubleshooting by Using Stored Procedures
sp_browsereplcmds – Commands waiting at Distributor
sp_replshowcmds – Commands waiting at Publisher
sp_repltrans – LSNs in transaction log
sp_replflush – Stop acting as the Log Reader Agent
sp_repldone – System use only
sp_replqueuemonitor – Lists queue messages
DBCC OPENTRAN – Returns oldest LSNs
sp_replcmds – System use only
![Page 35: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/35.jpg)
Practice: Troubleshooting by Using Stored Procedures
Create a push subscription and subscribe
Identify commands at Distributor
Identify commands at Publisher
![Page 36: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/36.jpg)
Skipping Errors to Prevent Replication Halts
![Page 37: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/37.jpg)
Reinitializing Subscriptions
![Page 38: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/38.jpg)
Troubleshooting Steps
Check Replication Monitor
Change -BatchCommitSize
Disable Cleanup
Rerun distribution
Check MSreplication_subscriptions
Identify the row
Narrow the query
Map the sequence number
Display commands
![Page 39: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/39.jpg)
Troubleshooting Guidelines
Use SQL error logs
Run DBCC checks
Check for blocking issues
Analyze index and query performance on subscribing tables
View application and System Event Viewer logs
Check triggers
![Page 40: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/40.jpg)
Lesson: Tuning Transactional Replication
Identifying Subscriber Factors That Degrade Performance
Improving Performance Through Design and Configuration
Improving Performance by Using Appropriate Subscription Types and Scheduling
Improving Performance by Using Agent Properties
![Page 41: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/41.jpg)
Identifying Subscriber Factors That Degrade Performance
Subscriber computer factors
Subscription database or SQL Server setup factors
Network speed or connection factors
Additional factors
![Page 42: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/42.jpg)
Improving Performance Through Design and Configuration
Design factors
Use custom stored procedures
Avoid individual row evaluation
Publish as indexed views instead of filtered tables
Avoid the update of unique constrained columns
Configuration factors
Set the distribution database to a fixed size
Configure the Distributor on a dedicated server
![Page 43: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/43.jpg)
Improving Performance by Using Appropriate Subscription Types and Scheduling
Subscription factors
Use push and pull subscriptions appropriately
Use anonymous subscriptions appropriately
Scheduling factors
Run agents continuously
Reduce distribution frequency
Schedule snapshots during periods of low activity
![Page 44: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/44.jpg)
Improving Performance by Using Agent Properties
Property of both the Log Reader Agent and Distribution Agent
Use -PollingInterval parameter to adjust latency Log Reader Agent Properties
Increase -ReadBatchSize parameter Retain -ReadBatchThreshold default Adjust the -MaxCmdsInTran setting
Distribution Agent Properties
Increase -CommitBatchSize and -CommitBatchThreshold defaults
![Page 45: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/45.jpg)
Review
Understanding Transactional Replication Architecture
Replicating with Transactional Replication
Implementing Updatable Transactional Replication
Facilitating Transactional Replication by Using Stored Procedures
Troubleshooting Transactional Replication
Tuning Transactional Replication
![Page 46: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/46.jpg)
Lab 4: Implementing Transactional Replication
Exercise 1: Designing a Transactional Replication Solution
![Page 47: Module 4: Implementing Transactional Replication](https://reader035.vdocuments.site/reader035/viewer/2022062314/56649e355503460f94b23c19/html5/thumbnails/47.jpg)
Course Evaluation