Jupp Heynckes' men were touted as a comfortable favorite for the game on Sunday, but ended up losing by the odd goal in five.
Andreas Ivanschitz opened the scoring in the first half, but Daniel van Buyten responded with a goal after the break. Marco Caligiuri restored the Oh-Fives' lead, and minutes later Niko Bungert doubled Mainz's advantage. Van Buyten popped up with another goal for the Bavarians, but it proved a mere consolation.
Surprisingly, Mainz was the better team in the early minutes of the game and looked the more likely to score the opener. A golden chance was wasted in the fifth minute, when Sami Allagui received the ball inside the box, but could only fire wide with Manuel Neuer beaten.
Thomas Tuchel's men were looking increasingly dangerous on the counterattack, and their efforts were finally rewarded with the opening strike in the 10th minute. A mistake by Luiz Gustavo allowed Nicolai Muller to thread a ball behind Bayern's defense for Ivanschitz, who rounded the goalkeeper before slotting home.
The visiting team's sloppiness continued in the moments immediately after the opener as the goalscorer was once again presented with a chance, but could only volley over the bar from inside the penalty area.
Bayern managed to pick itself up as the game progressed, but the closest the team went to scoring in the first half was in the 37th minute, when a free kick by Holger Badstuber rattled the bar.
The Bavarians threw the kitchen sink at the home side after the restart, and drew level in the 56th minute through Van Buyten, who headed in from a free kick by Toni Kroos from near the corner flag.
Against the run of play, Tuchel's men restored the lead shortly after the hour mark. Caligiuri was picked out well outside the box, from where he unleashed a precise shot towards the right corner, beating Manuel Neuer, who could only watch as the ball ended in the net.
The Bavarians looked shell-shocked by the development, but were in for another surprise 10 minutes later when Bungert headed in from a cross by Ivanschitz, to double Mainz's advantage.
Van Buyten hit back again, however, as in the 79th minute he gave the Bavarians hope again with another header, this time following a delightful pass by Kroos. However, it was too little, too late and the game finished 3-2.
The result means Bayern slips to third, behind Dortmund and Borussia Monchengladbach, while the win lifts Mainz out of the relegation zone.