Thiago Alcantara opened the scoring with a cool finish but the home side claimed vital points in the fight against relegation through substitute Diego Ifran and a Xabi Prieto penalty.
It was the first time both Real and Barca have lost a Liga match on a weekend for two years.
Barca started on the front foot, the irrepressible Lionel Messi blazing a first-time strike just wide from 20 yards and Ibrahim Afellay - who provided the assist for Messi's first in the Champions League semi-final first leg in the Bernabeu in midweek - also forcing a smart stop from Claudio Bravo.
Raul Tamudo, for years the goalscoring thorn in Barca's side while turning out for Espanyol in the city derby, caused them heartache of a different kind when his foul on Masia product and Barca B right-back Martin Montoya caused the 20-year-old to withdraw with an injury around the collarbone area.
The striker almost connected with a Prieto cross when in behind the away backline but was largely left to operate alone in attack, not an easy task against Gerard Pique and Gabriel Milito.
On 29 minutes Barca took the lead. Xavi, like Messi a surprise starter ahead of the Camp Nou leg of the semi-final on Tuesday, looked for the Argentina star but a rare instance of mis-control from him worked to the team's benefit as Thiago raced on to the ball and finished off the underside of the bar.
Messi has scored an astonishing 52 goals this season, but it was Jeffren who looked the more dangerous player operating on the right flank.
La Real's captain Mikel Aranburu went close soon after the break with a snapshot from 25 yards while at the other end Jeffren forced a save from Bravo.
Barca were trying to match the Basque club's record of 32 consecutive Liga matches unbeaten, set in the 1979-80 season, and looked good for it until that point. Sociedad however then began to attack in more numbers.
First Dani Alves, Montoya's replacement, almost scored an own-goal - although the flag was up against Antoine Griezmann - then veteran away keeper Jose Manuel Pinto had to save from Tamudo with his legs.
After Pinto twice punched clear under pressure in the 67th minute Barca almost snatched a second on the counter, Messi stealing the ball from Diego Rivas and covering most of the pitch before slipping to the right and Jeffren. His shot was saved by Bravo at the near post.
On 71 minutes the home side were level. There was confusion around the Barca penalty area and Frenchman Griezmann did well to turn the ball back in, where Ifran - who replaced Tamudo only two minutes previously - finished delicately.
Six minutes later Milito headed home a Xavi free-kick at the back post but was wrongly flagged offside - he was level - and got up only to be stricken by cramp.
For some reason Pinto passed a goal-kick to Mascherano near the corner flag, inviting pressure which resulted in the Argentina captain fouling David Zurutuza as he sprinted across into the box with the ball.
Prieto's low kick was woeful, even allowing a rooted Pinto to change the direction of his dive and almost get something on it, but the ball hit the net to give La Real a 2-1 lead.
Barca had two chances to equalise themselves. First Jeffren had a shot saved which Messi almost scored from on the rebound. Afellay then danced into the box and Bravo again made a stop, this time from point-blank range; Jeffren stabbed for goal only to see his shot blocked on the line and Thiago, also following up then blasted over from eight yards.
Real Sociedad are now six points clear of the drop zone while Barca's title is not yet won - although they remain clear favourites to retain it.
- Related links